a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1) // SPDX-License-Identifier: GPL-2.0
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 2) /*
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 3) * virtio-fs: Virtio Filesystem
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 4) * Copyright (C) 2018 Red Hat, Inc.
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 5) */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 6)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 7) #include <linux/fs.h>
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 8) #include <linux/dax.h>
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 9) #include <linux/pci.h>
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 10) #include <linux/pfn_t.h>
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 11) #include <linux/module.h>
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 12) #include <linux/virtio.h>
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 13) #include <linux/virtio_fs.h>
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 14) #include <linux/delay.h>
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 15) #include <linux/fs_context.h>
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 16) #include <linux/fs_parser.h>
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 17) #include <linux/highmem.h>
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 18) #include <linux/uio.h>
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 19) #include "fuse_i.h"
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 20)
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 21) /* Used to help calculate the FUSE connection's max_pages limit for a request's
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 22) * size. Parts of the struct fuse_req are sliced into scattergather lists in
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 23) * addition to the pages used, so this can help account for that overhead.
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 24) */
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 25) #define FUSE_HEADER_OVERHEAD 4
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 26)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 27) /* List of virtio-fs device instances and a lock for the list. Also provides
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 28) * mutual exclusion in device removal and mounting path
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 29) */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 30) static DEFINE_MUTEX(virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 31) static LIST_HEAD(virtio_fs_instances);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 32)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 33) enum {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 34) VQ_HIPRIO,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 35) VQ_REQUEST
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 36) };
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 37)
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 38) #define VQ_NAME_LEN 24
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 39)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 40) /* Per-virtqueue state */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 41) struct virtio_fs_vq {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 42) spinlock_t lock;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 43) struct virtqueue *vq; /* protected by ->lock */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 44) struct work_struct done_work;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 45) struct list_head queued_reqs;
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 46) struct list_head end_reqs; /* End these requests */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 47) struct delayed_work dispatch_work;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 48) struct fuse_dev *fud;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 49) bool connected;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 50) long in_flight;
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 51) struct completion in_flight_zero; /* No inflight requests */
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 52) char name[VQ_NAME_LEN];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 53) } ____cacheline_aligned_in_smp;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 54)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 55) /* A virtio-fs device instance */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 56) struct virtio_fs {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 57) struct kref refcount;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 58) struct list_head list; /* on virtio_fs_instances */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 59) char *tag;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 60) struct virtio_fs_vq *vqs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 61) unsigned int nvqs; /* number of virtqueues */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 62) unsigned int num_request_queues; /* number of request queues */
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 63) struct dax_device *dax_dev;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 64)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 65) /* DAX memory window where file contents are mapped */
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 66) void *window_kaddr;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 67) phys_addr_t window_phys_addr;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 68) size_t window_len;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 69) };
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 70)
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 71) struct virtio_fs_forget_req {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 72) struct fuse_in_header ih;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 73) struct fuse_forget_in arg;
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 74) };
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 75)
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 76) struct virtio_fs_forget {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 77) /* This request can be temporarily queued on virt queue */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 78) struct list_head list;
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 79) struct virtio_fs_forget_req req;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 80) };
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 81)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 82) struct virtio_fs_req_work {
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 83) struct fuse_req *req;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 84) struct virtio_fs_vq *fsvq;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 85) struct work_struct done_work;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 86) };
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 87)
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 88) static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 89) struct fuse_req *req, bool in_flight);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 90)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 91) enum {
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 92) OPT_DAX,
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 93) };
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 94)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 95) static const struct fs_parameter_spec virtio_fs_parameters[] = {
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 96) fsparam_flag("dax", OPT_DAX),
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 97) {}
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 98) };
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 99)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 100) static int virtio_fs_parse_param(struct fs_context *fc,
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 101) struct fs_parameter *param)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 102) {
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 103) struct fs_parse_result result;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 104) struct fuse_fs_context *ctx = fc->fs_private;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 105) int opt;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 106)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 107) opt = fs_parse(fc, virtio_fs_parameters, param, &result);
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 108) if (opt < 0)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 109) return opt;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 110)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 111) switch (opt) {
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 112) case OPT_DAX:
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 113) ctx->dax = 1;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 114) break;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 115) default:
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 116) return -EINVAL;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 117) }
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 118)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 119) return 0;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 120) }
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 121)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 122) static void virtio_fs_free_fc(struct fs_context *fc)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 123) {
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 124) struct fuse_fs_context *ctx = fc->fs_private;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 125)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 126) kfree(ctx);
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 127) }
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 128)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 129) static inline struct virtio_fs_vq *vq_to_fsvq(struct virtqueue *vq)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 130) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 131) struct virtio_fs *fs = vq->vdev->priv;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 132)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 133) return &fs->vqs[vq->index];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 134) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 135)
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 136) /* Should be called with fsvq->lock held. */
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 137) static inline void inc_in_flight_req(struct virtio_fs_vq *fsvq)
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 138) {
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 139) fsvq->in_flight++;
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 140) }
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 141)
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 142) /* Should be called with fsvq->lock held. */
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 143) static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 144) {
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 145) WARN_ON(fsvq->in_flight <= 0);
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 146) fsvq->in_flight--;
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 147) if (!fsvq->in_flight)
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 148) complete(&fsvq->in_flight_zero);
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 149) }
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 150)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 151) static void release_virtio_fs_obj(struct kref *ref)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 152) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 153) struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 154)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 155) kfree(vfs->vqs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 156) kfree(vfs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 157) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 158)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 159) /* Make sure virtiofs_mutex is held */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 160) static void virtio_fs_put(struct virtio_fs *fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 161) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 162) kref_put(&fs->refcount, release_virtio_fs_obj);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 163) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 164)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 165) static void virtio_fs_fiq_release(struct fuse_iqueue *fiq)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 166) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 167) struct virtio_fs *vfs = fiq->priv;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 168)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 169) mutex_lock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 170) virtio_fs_put(vfs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 171) mutex_unlock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 172) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 173)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 174) static void virtio_fs_drain_queue(struct virtio_fs_vq *fsvq)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 175) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 176) WARN_ON(fsvq->in_flight < 0);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 177)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 178) /* Wait for in flight requests to finish.*/
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 179) spin_lock(&fsvq->lock);
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 180) if (fsvq->in_flight) {
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 181) /* We are holding virtio_fs_mutex. There should not be any
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 182) * waiters waiting for completion.
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 183) */
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 184) reinit_completion(&fsvq->in_flight_zero);
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 185) spin_unlock(&fsvq->lock);
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 186) wait_for_completion(&fsvq->in_flight_zero);
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 187) } else {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 188) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 189) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 190)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 191) flush_work(&fsvq->done_work);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 192) flush_delayed_work(&fsvq->dispatch_work);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 193) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 194)
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 195) static void virtio_fs_drain_all_queues_locked(struct virtio_fs *fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 196) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 197) struct virtio_fs_vq *fsvq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 198) int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 199)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 200) for (i = 0; i < fs->nvqs; i++) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 201) fsvq = &fs->vqs[i];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 202) virtio_fs_drain_queue(fsvq);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 203) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 204) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 205)
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 206) static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 207) {
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 208) /* Provides mutual exclusion between ->remove and ->kill_sb
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 209) * paths. We don't want both of these draining queue at the
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 210) * same time. Current completion logic reinits completion
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 211) * and that means there should not be any other thread
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 212) * doing reinit or waiting for completion already.
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 213) */
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 214) mutex_lock(&virtio_fs_mutex);
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 215) virtio_fs_drain_all_queues_locked(fs);
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 216) mutex_unlock(&virtio_fs_mutex);
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 217) }
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 218)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 219) static void virtio_fs_start_all_queues(struct virtio_fs *fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 220) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 221) struct virtio_fs_vq *fsvq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 222) int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 223)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 224) for (i = 0; i < fs->nvqs; i++) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 225) fsvq = &fs->vqs[i];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 226) spin_lock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 227) fsvq->connected = true;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 228) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 229) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 230) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 231)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 232) /* Add a new instance to the list or return -EEXIST if tag name exists*/
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 233) static int virtio_fs_add_instance(struct virtio_fs *fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 234) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 235) struct virtio_fs *fs2;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 236) bool duplicate = false;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 237)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 238) mutex_lock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 239)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 240) list_for_each_entry(fs2, &virtio_fs_instances, list) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 241) if (strcmp(fs->tag, fs2->tag) == 0)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 242) duplicate = true;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 243) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 244)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 245) if (!duplicate)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 246) list_add_tail(&fs->list, &virtio_fs_instances);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 247)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 248) mutex_unlock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 249)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 250) if (duplicate)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 251) return -EEXIST;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 252) return 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 253) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 254)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 255) /* Return the virtio_fs with a given tag, or NULL */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 256) static struct virtio_fs *virtio_fs_find_instance(const char *tag)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 257) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 258) struct virtio_fs *fs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 259)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 260) mutex_lock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 261)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 262) list_for_each_entry(fs, &virtio_fs_instances, list) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 263) if (strcmp(fs->tag, tag) == 0) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 264) kref_get(&fs->refcount);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 265) goto found;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 266) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 267) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 268)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 269) fs = NULL; /* not found */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 270)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 271) found:
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 272) mutex_unlock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 273)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 274) return fs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 275) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 276)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 277) static void virtio_fs_free_devs(struct virtio_fs *fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 278) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 279) unsigned int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 280)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 281) for (i = 0; i < fs->nvqs; i++) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 282) struct virtio_fs_vq *fsvq = &fs->vqs[i];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 283)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 284) if (!fsvq->fud)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 285) continue;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 286)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 287) fuse_dev_free(fsvq->fud);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 288) fsvq->fud = NULL;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 289) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 290) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 291)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 292) /* Read filesystem name from virtio config into fs->tag (must kfree()). */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 293) static int virtio_fs_read_tag(struct virtio_device *vdev, struct virtio_fs *fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 294) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 295) char tag_buf[sizeof_field(struct virtio_fs_config, tag)];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 296) char *end;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 297) size_t len;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 298)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 299) virtio_cread_bytes(vdev, offsetof(struct virtio_fs_config, tag),
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 300) &tag_buf, sizeof(tag_buf));
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 301) end = memchr(tag_buf, '\0', sizeof(tag_buf));
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 302) if (end == tag_buf)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 303) return -EINVAL; /* empty tag */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 304) if (!end)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 305) end = &tag_buf[sizeof(tag_buf)];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 306)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 307) len = end - tag_buf;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 308) fs->tag = devm_kmalloc(&vdev->dev, len + 1, GFP_KERNEL);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 309) if (!fs->tag)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 310) return -ENOMEM;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 311) memcpy(fs->tag, tag_buf, len);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 312) fs->tag[len] = '\0';
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 313) return 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 314) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 315)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 316) /* Work function for hiprio completion */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 317) static void virtio_fs_hiprio_done_work(struct work_struct *work)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 318) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 319) struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 320) done_work);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 321) struct virtqueue *vq = fsvq->vq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 322)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 323) /* Free completed FUSE_FORGET requests */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 324) spin_lock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 325) do {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 326) unsigned int len;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 327) void *req;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 328)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 329) virtqueue_disable_cb(vq);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 330)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 331) while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 332) kfree(req);
c17ea00961036 (Vivek Goyal 2019-10-15 13:46:25 -0400 333) dec_in_flight_req(fsvq);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 334) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 335) } while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq)));
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 336) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 337) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 338)
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 339) static void virtio_fs_request_dispatch_work(struct work_struct *work)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 340) {
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 341) struct fuse_req *req;
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 342) struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 343) dispatch_work.work);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 344) int ret;
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 345)
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 346) pr_debug("virtio-fs: worker %s called.\n", __func__);
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 347) while (1) {
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 348) spin_lock(&fsvq->lock);
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 349) req = list_first_entry_or_null(&fsvq->end_reqs, struct fuse_req,
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 350) list);
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 351) if (!req) {
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 352) spin_unlock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 353) break;
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 354) }
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 355)
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 356) list_del_init(&req->list);
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 357) spin_unlock(&fsvq->lock);
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 358) fuse_request_end(req);
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 359) }
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 360)
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 361) /* Dispatch pending requests */
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 362) while (1) {
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 363) spin_lock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 364) req = list_first_entry_or_null(&fsvq->queued_reqs,
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 365) struct fuse_req, list);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 366) if (!req) {
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 367) spin_unlock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 368) return;
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 369) }
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 370) list_del_init(&req->list);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 371) spin_unlock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 372)
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 373) ret = virtio_fs_enqueue_req(fsvq, req, true);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 374) if (ret < 0) {
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 375) if (ret == -ENOMEM || ret == -ENOSPC) {
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 376) spin_lock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 377) list_add_tail(&req->list, &fsvq->queued_reqs);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 378) schedule_delayed_work(&fsvq->dispatch_work,
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 379) msecs_to_jiffies(1));
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 380) spin_unlock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 381) return;
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 382) }
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 383) req->out.h.error = ret;
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 384) spin_lock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 385) dec_in_flight_req(fsvq);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 386) spin_unlock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 387) pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n",
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 388) ret);
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 389) fuse_request_end(req);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 390) }
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 391) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 392) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 393)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 394) /*
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 395) * Returns 1 if queue is full and sender should wait a bit before sending
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 396) * next request, 0 otherwise.
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 397) */
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 398) static int send_forget_request(struct virtio_fs_vq *fsvq,
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 399) struct virtio_fs_forget *forget,
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 400) bool in_flight)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 401) {
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 402) struct scatterlist sg;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 403) struct virtqueue *vq;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 404) int ret = 0;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 405) bool notify;
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 406) struct virtio_fs_forget_req *req = &forget->req;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 407)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 408) spin_lock(&fsvq->lock);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 409) if (!fsvq->connected) {
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 410) if (in_flight)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 411) dec_in_flight_req(fsvq);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 412) kfree(forget);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 413) goto out;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 414) }
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 415)
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 416) sg_init_one(&sg, req, sizeof(*req));
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 417) vq = fsvq->vq;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 418) dev_dbg(&vq->vdev->dev, "%s\n", __func__);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 419)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 420) ret = virtqueue_add_outbuf(vq, &sg, 1, forget, GFP_ATOMIC);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 421) if (ret < 0) {
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 422) if (ret == -ENOMEM || ret == -ENOSPC) {
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 423) pr_debug("virtio-fs: Could not queue FORGET: err=%d. Will try later\n",
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 424) ret);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 425) list_add_tail(&forget->list, &fsvq->queued_reqs);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 426) schedule_delayed_work(&fsvq->dispatch_work,
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 427) msecs_to_jiffies(1));
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 428) if (!in_flight)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 429) inc_in_flight_req(fsvq);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 430) /* Queue is full */
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 431) ret = 1;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 432) } else {
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 433) pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 434) ret);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 435) kfree(forget);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 436) if (in_flight)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 437) dec_in_flight_req(fsvq);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 438) }
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 439) goto out;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 440) }
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 441)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 442) if (!in_flight)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 443) inc_in_flight_req(fsvq);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 444) notify = virtqueue_kick_prepare(vq);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 445) spin_unlock(&fsvq->lock);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 446)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 447) if (notify)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 448) virtqueue_notify(vq);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 449) return ret;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 450) out:
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 451) spin_unlock(&fsvq->lock);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 452) return ret;
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 453) }
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 454)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 455) static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 456) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 457) struct virtio_fs_forget *forget;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 458) struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 459) dispatch_work.work);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 460) pr_debug("virtio-fs: worker %s called.\n", __func__);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 461) while (1) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 462) spin_lock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 463) forget = list_first_entry_or_null(&fsvq->queued_reqs,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 464) struct virtio_fs_forget, list);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 465) if (!forget) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 466) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 467) return;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 468) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 469)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 470) list_del(&forget->list);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 471) spin_unlock(&fsvq->lock);
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 472) if (send_forget_request(fsvq, forget, true))
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 473) return;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 474) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 475) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 476)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 477) /* Allocate and copy args into req->argbuf */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 478) static int copy_args_to_argbuf(struct fuse_req *req)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 479) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 480) struct fuse_args *args = req->args;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 481) unsigned int offset = 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 482) unsigned int num_in;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 483) unsigned int num_out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 484) unsigned int len;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 485) unsigned int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 486)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 487) num_in = args->in_numargs - args->in_pages;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 488) num_out = args->out_numargs - args->out_pages;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 489) len = fuse_len_args(num_in, (struct fuse_arg *) args->in_args) +
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 490) fuse_len_args(num_out, args->out_args);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 491)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 492) req->argbuf = kmalloc(len, GFP_ATOMIC);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 493) if (!req->argbuf)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 494) return -ENOMEM;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 495)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 496) for (i = 0; i < num_in; i++) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 497) memcpy(req->argbuf + offset,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 498) args->in_args[i].value,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 499) args->in_args[i].size);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 500) offset += args->in_args[i].size;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 501) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 502)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 503) return 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 504) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 505)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 506) /* Copy args out of and free req->argbuf */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 507) static void copy_args_from_argbuf(struct fuse_args *args, struct fuse_req *req)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 508) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 509) unsigned int remaining;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 510) unsigned int offset;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 511) unsigned int num_in;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 512) unsigned int num_out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 513) unsigned int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 514)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 515) remaining = req->out.h.len - sizeof(req->out.h);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 516) num_in = args->in_numargs - args->in_pages;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 517) num_out = args->out_numargs - args->out_pages;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 518) offset = fuse_len_args(num_in, (struct fuse_arg *)args->in_args);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 519)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 520) for (i = 0; i < num_out; i++) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 521) unsigned int argsize = args->out_args[i].size;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 522)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 523) if (args->out_argvar &&
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 524) i == args->out_numargs - 1 &&
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 525) argsize > remaining) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 526) argsize = remaining;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 527) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 528)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 529) memcpy(args->out_args[i].value, req->argbuf + offset, argsize);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 530) offset += argsize;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 531)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 532) if (i != args->out_numargs - 1)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 533) remaining -= argsize;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 534) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 535)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 536) /* Store the actual size of the variable-length arg */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 537) if (args->out_argvar)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 538) args->out_args[args->out_numargs - 1].size = remaining;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 539)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 540) kfree(req->argbuf);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 541) req->argbuf = NULL;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 542) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 543)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 544) /* Work function for request completion */
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 545) static void virtio_fs_request_complete(struct fuse_req *req,
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 546) struct virtio_fs_vq *fsvq)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 547) {
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 548) struct fuse_pqueue *fpq = &fsvq->fud->pq;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 549) struct fuse_args *args;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 550) struct fuse_args_pages *ap;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 551) unsigned int len, i, thislen;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 552) struct page *page;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 553)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 554) /*
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 555) * TODO verify that server properly follows FUSE protocol
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 556) * (oh.uniq, oh.len)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 557) */
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 558) args = req->args;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 559) copy_args_from_argbuf(args, req);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 560)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 561) if (args->out_pages && args->page_zeroing) {
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 562) len = args->out_args[args->out_numargs - 1].size;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 563) ap = container_of(args, typeof(*ap), args);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 564) for (i = 0; i < ap->num_pages; i++) {
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 565) thislen = ap->descs[i].length;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 566) if (len < thislen) {
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 567) WARN_ON(ap->descs[i].offset);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 568) page = ap->pages[i];
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 569) zero_user_segment(page, len, thislen);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 570) len = 0;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 571) } else {
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 572) len -= thislen;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 573) }
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 574) }
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 575) }
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 576)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 577) spin_lock(&fpq->lock);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 578) clear_bit(FR_SENT, &req->flags);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 579) spin_unlock(&fpq->lock);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 580)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 581) fuse_request_end(req);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 582) spin_lock(&fsvq->lock);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 583) dec_in_flight_req(fsvq);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 584) spin_unlock(&fsvq->lock);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 585) }
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 586)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 587) static void virtio_fs_complete_req_work(struct work_struct *work)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 588) {
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 589) struct virtio_fs_req_work *w =
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 590) container_of(work, typeof(*w), done_work);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 591)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 592) virtio_fs_request_complete(w->req, w->fsvq);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 593) kfree(w);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 594) }
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 595)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 596) static void virtio_fs_requests_done_work(struct work_struct *work)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 597) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 598) struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 599) done_work);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 600) struct fuse_pqueue *fpq = &fsvq->fud->pq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 601) struct virtqueue *vq = fsvq->vq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 602) struct fuse_req *req;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 603) struct fuse_req *next;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 604) unsigned int len;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 605) LIST_HEAD(reqs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 606)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 607) /* Collect completed requests off the virtqueue */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 608) spin_lock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 609) do {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 610) virtqueue_disable_cb(vq);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 611)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 612) while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 613) spin_lock(&fpq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 614) list_move_tail(&req->list, &reqs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 615) spin_unlock(&fpq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 616) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 617) } while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq)));
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 618) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 619)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 620) /* End requests */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 621) list_for_each_entry_safe(req, next, &reqs, list) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 622) list_del_init(&req->list);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 623)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 624) /* blocking async request completes in a worker context */
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 625) if (req->args->may_block) {
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 626) struct virtio_fs_req_work *w;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 627)
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 628) w = kzalloc(sizeof(*w), GFP_NOFS | __GFP_NOFAIL);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 629) INIT_WORK(&w->done_work, virtio_fs_complete_req_work);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 630) w->fsvq = fsvq;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 631) w->req = req;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 632) schedule_work(&w->done_work);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 633) } else {
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 634) virtio_fs_request_complete(req, fsvq);
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 635) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 636) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 637) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 638)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 639) /* Virtqueue interrupt handler */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 640) static void virtio_fs_vq_done(struct virtqueue *vq)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 641) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 642) struct virtio_fs_vq *fsvq = vq_to_fsvq(vq);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 643)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 644) dev_dbg(&vq->vdev->dev, "%s %s\n", __func__, fsvq->name);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 645)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 646) schedule_work(&fsvq->done_work);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 647) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 648)
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 649) static void virtio_fs_init_vq(struct virtio_fs_vq *fsvq, char *name,
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 650) int vq_type)
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 651) {
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 652) strncpy(fsvq->name, name, VQ_NAME_LEN);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 653) spin_lock_init(&fsvq->lock);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 654) INIT_LIST_HEAD(&fsvq->queued_reqs);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 655) INIT_LIST_HEAD(&fsvq->end_reqs);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 656) init_completion(&fsvq->in_flight_zero);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 657)
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 658) if (vq_type == VQ_REQUEST) {
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 659) INIT_WORK(&fsvq->done_work, virtio_fs_requests_done_work);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 660) INIT_DELAYED_WORK(&fsvq->dispatch_work,
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 661) virtio_fs_request_dispatch_work);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 662) } else {
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 663) INIT_WORK(&fsvq->done_work, virtio_fs_hiprio_done_work);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 664) INIT_DELAYED_WORK(&fsvq->dispatch_work,
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 665) virtio_fs_hiprio_dispatch_work);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 666) }
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 667) }
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 668)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 669) /* Initialize virtqueues */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 670) static int virtio_fs_setup_vqs(struct virtio_device *vdev,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 671) struct virtio_fs *fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 672) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 673) struct virtqueue **vqs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 674) vq_callback_t **callbacks;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 675) const char **names;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 676) unsigned int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 677) int ret = 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 678)
2c0349ec1a8ee (Michael S. Tsirkin 2020-08-05 05:39:36 -0400 679) virtio_cread_le(vdev, struct virtio_fs_config, num_request_queues,
2c0349ec1a8ee (Michael S. Tsirkin 2020-08-05 05:39:36 -0400 680) &fs->num_request_queues);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 681) if (fs->num_request_queues == 0)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 682) return -EINVAL;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 683)
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 684) fs->nvqs = VQ_REQUEST + fs->num_request_queues;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 685) fs->vqs = kcalloc(fs->nvqs, sizeof(fs->vqs[VQ_HIPRIO]), GFP_KERNEL);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 686) if (!fs->vqs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 687) return -ENOMEM;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 688)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 689) vqs = kmalloc_array(fs->nvqs, sizeof(vqs[VQ_HIPRIO]), GFP_KERNEL);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 690) callbacks = kmalloc_array(fs->nvqs, sizeof(callbacks[VQ_HIPRIO]),
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 691) GFP_KERNEL);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 692) names = kmalloc_array(fs->nvqs, sizeof(names[VQ_HIPRIO]), GFP_KERNEL);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 693) if (!vqs || !callbacks || !names) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 694) ret = -ENOMEM;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 695) goto out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 696) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 697)
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 698) /* Initialize the hiprio/forget request virtqueue */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 699) callbacks[VQ_HIPRIO] = virtio_fs_vq_done;
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 700) virtio_fs_init_vq(&fs->vqs[VQ_HIPRIO], "hiprio", VQ_HIPRIO);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 701) names[VQ_HIPRIO] = fs->vqs[VQ_HIPRIO].name;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 702)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 703) /* Initialize the requests virtqueues */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 704) for (i = VQ_REQUEST; i < fs->nvqs; i++) {
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 705) char vq_name[VQ_NAME_LEN];
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 706)
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 707) snprintf(vq_name, VQ_NAME_LEN, "requests.%u", i - VQ_REQUEST);
b43b7e81eb2b1 (Vivek Goyal 2020-08-19 18:19:44 -0400 708) virtio_fs_init_vq(&fs->vqs[i], vq_name, VQ_REQUEST);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 709) callbacks[i] = virtio_fs_vq_done;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 710) names[i] = fs->vqs[i].name;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 711) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 712)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 713) ret = virtio_find_vqs(vdev, fs->nvqs, vqs, callbacks, names, NULL);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 714) if (ret < 0)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 715) goto out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 716)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 717) for (i = 0; i < fs->nvqs; i++)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 718) fs->vqs[i].vq = vqs[i];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 719)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 720) virtio_fs_start_all_queues(fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 721) out:
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 722) kfree(names);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 723) kfree(callbacks);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 724) kfree(vqs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 725) if (ret)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 726) kfree(fs->vqs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 727) return ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 728) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 729)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 730) /* Free virtqueues (device must already be reset) */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 731) static void virtio_fs_cleanup_vqs(struct virtio_device *vdev,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 732) struct virtio_fs *fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 733) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 734) vdev->config->del_vqs(vdev);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 735) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 736)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 737) /* Map a window offset to a page frame number. The window offset will have
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 738) * been produced by .iomap_begin(), which maps a file offset to a window
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 739) * offset.
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 740) */
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 741) static long virtio_fs_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 742) long nr_pages, void **kaddr, pfn_t *pfn)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 743) {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 744) struct virtio_fs *fs = dax_get_private(dax_dev);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 745) phys_addr_t offset = PFN_PHYS(pgoff);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 746) size_t max_nr_pages = fs->window_len/PAGE_SIZE - pgoff;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 747)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 748) if (kaddr)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 749) *kaddr = fs->window_kaddr + offset;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 750) if (pfn)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 751) *pfn = phys_to_pfn_t(fs->window_phys_addr + offset,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 752) PFN_DEV | PFN_MAP);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 753) return nr_pages > max_nr_pages ? max_nr_pages : nr_pages;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 754) }
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 755)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 756) static size_t virtio_fs_copy_from_iter(struct dax_device *dax_dev,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 757) pgoff_t pgoff, void *addr,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 758) size_t bytes, struct iov_iter *i)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 759) {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 760) return copy_from_iter(addr, bytes, i);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 761) }
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 762)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 763) static size_t virtio_fs_copy_to_iter(struct dax_device *dax_dev,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 764) pgoff_t pgoff, void *addr,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 765) size_t bytes, struct iov_iter *i)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 766) {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 767) return copy_to_iter(addr, bytes, i);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 768) }
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 769)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 770) static int virtio_fs_zero_page_range(struct dax_device *dax_dev,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 771) pgoff_t pgoff, size_t nr_pages)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 772) {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 773) long rc;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 774) void *kaddr;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 775)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 776) rc = dax_direct_access(dax_dev, pgoff, nr_pages, &kaddr, NULL);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 777) if (rc < 0)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 778) return rc;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 779) memset(kaddr, 0, nr_pages << PAGE_SHIFT);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 780) dax_flush(dax_dev, kaddr, nr_pages << PAGE_SHIFT);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 781) return 0;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 782) }
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 783)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 784) static const struct dax_operations virtio_fs_dax_ops = {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 785) .direct_access = virtio_fs_direct_access,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 786) .copy_from_iter = virtio_fs_copy_from_iter,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 787) .copy_to_iter = virtio_fs_copy_to_iter,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 788) .zero_page_range = virtio_fs_zero_page_range,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 789) };
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 790)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 791) static void virtio_fs_cleanup_dax(void *data)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 792) {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 793) struct dax_device *dax_dev = data;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 794)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 795) kill_dax(dax_dev);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 796) put_dax(dax_dev);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 797) }
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 798)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 799) static int virtio_fs_setup_dax(struct virtio_device *vdev, struct virtio_fs *fs)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 800) {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 801) struct virtio_shm_region cache_reg;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 802) struct dev_pagemap *pgmap;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 803) bool have_cache;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 804)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 805) if (!IS_ENABLED(CONFIG_FUSE_DAX))
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 806) return 0;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 807)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 808) /* Get cache region */
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 809) have_cache = virtio_get_shm_region(vdev, &cache_reg,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 810) (u8)VIRTIO_FS_SHMCAP_ID_CACHE);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 811) if (!have_cache) {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 812) dev_notice(&vdev->dev, "%s: No cache capability\n", __func__);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 813) return 0;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 814) }
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 815)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 816) if (!devm_request_mem_region(&vdev->dev, cache_reg.addr, cache_reg.len,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 817) dev_name(&vdev->dev))) {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 818) dev_warn(&vdev->dev, "could not reserve region addr=0x%llx len=0x%llx\n",
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 819) cache_reg.addr, cache_reg.len);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 820) return -EBUSY;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 821) }
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 822)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 823) dev_notice(&vdev->dev, "Cache len: 0x%llx @ 0x%llx\n", cache_reg.len,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 824) cache_reg.addr);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 825)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 826) pgmap = devm_kzalloc(&vdev->dev, sizeof(*pgmap), GFP_KERNEL);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 827) if (!pgmap)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 828) return -ENOMEM;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 829)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 830) pgmap->type = MEMORY_DEVICE_FS_DAX;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 831)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 832) /* Ideally we would directly use the PCI BAR resource but
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 833) * devm_memremap_pages() wants its own copy in pgmap. So
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 834) * initialize a struct resource from scratch (only the start
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 835) * and end fields will be used).
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 836) */
694565356c2e0 (Linus Torvalds 2020-10-19 14:28:30 -0700 837) pgmap->range = (struct range) {
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 838) .start = (phys_addr_t) cache_reg.addr,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 839) .end = (phys_addr_t) cache_reg.addr + cache_reg.len - 1,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 840) };
694565356c2e0 (Linus Torvalds 2020-10-19 14:28:30 -0700 841) pgmap->nr_range = 1;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 842)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 843) fs->window_kaddr = devm_memremap_pages(&vdev->dev, pgmap);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 844) if (IS_ERR(fs->window_kaddr))
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 845) return PTR_ERR(fs->window_kaddr);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 846)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 847) fs->window_phys_addr = (phys_addr_t) cache_reg.addr;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 848) fs->window_len = (phys_addr_t) cache_reg.len;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 849)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 850) dev_dbg(&vdev->dev, "%s: window kaddr 0x%px phys_addr 0x%llx len 0x%llx\n",
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 851) __func__, fs->window_kaddr, cache_reg.addr, cache_reg.len);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 852)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 853) fs->dax_dev = alloc_dax(fs, NULL, &virtio_fs_dax_ops, 0);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 854) if (IS_ERR(fs->dax_dev))
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 855) return PTR_ERR(fs->dax_dev);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 856)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 857) return devm_add_action_or_reset(&vdev->dev, virtio_fs_cleanup_dax,
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 858) fs->dax_dev);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 859) }
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 860)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 861) static int virtio_fs_probe(struct virtio_device *vdev)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 862) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 863) struct virtio_fs *fs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 864) int ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 865)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 866) fs = kzalloc(sizeof(*fs), GFP_KERNEL);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 867) if (!fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 868) return -ENOMEM;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 869) kref_init(&fs->refcount);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 870) vdev->priv = fs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 871)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 872) ret = virtio_fs_read_tag(vdev, fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 873) if (ret < 0)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 874) goto out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 875)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 876) ret = virtio_fs_setup_vqs(vdev, fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 877) if (ret < 0)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 878) goto out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 879)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 880) /* TODO vq affinity */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 881)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 882) ret = virtio_fs_setup_dax(vdev, fs);
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 883) if (ret < 0)
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 884) goto out_vqs;
22f3787e9d95e (Stefan Hajnoczi 2020-08-19 18:19:46 -0400 885)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 886) /* Bring the device online in case the filesystem is mounted and
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 887) * requests need to be sent before we return.
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 888) */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 889) virtio_device_ready(vdev);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 890)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 891) ret = virtio_fs_add_instance(fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 892) if (ret < 0)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 893) goto out_vqs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 894)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 895) return 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 896)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 897) out_vqs:
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 898) vdev->config->reset(vdev);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 899) virtio_fs_cleanup_vqs(vdev, fs);
c79c5e0178922 (Luis Henriques 2021-03-17 08:44:43 +0000 900) kfree(fs->vqs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 901)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 902) out:
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 903) vdev->priv = NULL;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 904) kfree(fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 905) return ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 906) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 907)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 908) static void virtio_fs_stop_all_queues(struct virtio_fs *fs)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 909) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 910) struct virtio_fs_vq *fsvq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 911) int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 912)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 913) for (i = 0; i < fs->nvqs; i++) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 914) fsvq = &fs->vqs[i];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 915) spin_lock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 916) fsvq->connected = false;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 917) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 918) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 919) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 920)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 921) static void virtio_fs_remove(struct virtio_device *vdev)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 922) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 923) struct virtio_fs *fs = vdev->priv;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 924)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 925) mutex_lock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 926) /* This device is going away. No one should get new reference */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 927) list_del_init(&fs->list);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 928) virtio_fs_stop_all_queues(fs);
724c15a43e2c7 (Vivek Goyal 2019-10-30 11:07:19 -0400 929) virtio_fs_drain_all_queues_locked(fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 930) vdev->config->reset(vdev);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 931) virtio_fs_cleanup_vqs(vdev, fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 932)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 933) vdev->priv = NULL;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 934) /* Put device reference on virtio_fs object */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 935) virtio_fs_put(fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 936) mutex_unlock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 937) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 938)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 939) #ifdef CONFIG_PM_SLEEP
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 940) static int virtio_fs_freeze(struct virtio_device *vdev)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 941) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 942) /* TODO need to save state here */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 943) pr_warn("virtio-fs: suspend/resume not yet supported\n");
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 944) return -EOPNOTSUPP;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 945) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 946)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 947) static int virtio_fs_restore(struct virtio_device *vdev)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 948) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 949) /* TODO need to restore state here */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 950) return 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 951) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 952) #endif /* CONFIG_PM_SLEEP */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 953)
00929447f5758 (YueHaibing 2019-11-11 20:23:59 +0800 954) static const struct virtio_device_id id_table[] = {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 955) { VIRTIO_ID_FS, VIRTIO_DEV_ANY_ID },
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 956) {},
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 957) };
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 958)
00929447f5758 (YueHaibing 2019-11-11 20:23:59 +0800 959) static const unsigned int feature_table[] = {};
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 960)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 961) static struct virtio_driver virtio_fs_driver = {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 962) .driver.name = KBUILD_MODNAME,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 963) .driver.owner = THIS_MODULE,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 964) .id_table = id_table,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 965) .feature_table = feature_table,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 966) .feature_table_size = ARRAY_SIZE(feature_table),
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 967) .probe = virtio_fs_probe,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 968) .remove = virtio_fs_remove,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 969) #ifdef CONFIG_PM_SLEEP
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 970) .freeze = virtio_fs_freeze,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 971) .restore = virtio_fs_restore,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 972) #endif
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 973) };
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 974)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 975) static void virtio_fs_wake_forget_and_unlock(struct fuse_iqueue *fiq)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 976) __releases(fiq->lock)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 977) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 978) struct fuse_forget_link *link;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 979) struct virtio_fs_forget *forget;
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 980) struct virtio_fs_forget_req *req;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 981) struct virtio_fs *fs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 982) struct virtio_fs_vq *fsvq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 983) u64 unique;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 984)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 985) link = fuse_dequeue_forget(fiq, 1, NULL);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 986) unique = fuse_get_unique(fiq);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 987)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 988) fs = fiq->priv;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 989) fsvq = &fs->vqs[VQ_HIPRIO];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 990) spin_unlock(&fiq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 991)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 992) /* Allocate a buffer for the request */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 993) forget = kmalloc(sizeof(*forget), GFP_NOFS | __GFP_NOFAIL);
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 994) req = &forget->req;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 995)
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 996) req->ih = (struct fuse_in_header){
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 997) .opcode = FUSE_FORGET,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 998) .nodeid = link->forget_one.nodeid,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 999) .unique = unique,
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 1000) .len = sizeof(*req),
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1001) };
1efcf39eb6275 (Vivek Goyal 2019-10-30 11:07:18 -0400 1002) req->arg = (struct fuse_forget_in){
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1003) .nlookup = link->forget_one.nlookup,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1004) };
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1005)
58ada94f95f71 (Vivek Goyal 2019-10-30 11:07:17 -0400 1006) send_forget_request(fsvq, forget, false);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1007) kfree(link);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1008) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1009)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1010) static void virtio_fs_wake_interrupt_and_unlock(struct fuse_iqueue *fiq)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1011) __releases(fiq->lock)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1012) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1013) /*
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1014) * TODO interrupts.
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1015) *
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1016) * Normal fs operations on a local filesystems aren't interruptible.
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1017) * Exceptions are blocking lock operations; for example fcntl(F_SETLKW)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1018) * with shared lock between host and guest.
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1019) */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1020) spin_unlock(&fiq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1021) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1022)
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1023) /* Count number of scatter-gather elements required */
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1024) static unsigned int sg_count_fuse_pages(struct fuse_page_desc *page_descs,
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1025) unsigned int num_pages,
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1026) unsigned int total_len)
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1027) {
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1028) unsigned int i;
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1029) unsigned int this_len;
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1030)
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1031) for (i = 0; i < num_pages && total_len; i++) {
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1032) this_len = min(page_descs[i].length, total_len);
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1033) total_len -= this_len;
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1034) }
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1035)
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1036) return i;
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1037) }
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1038)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1039) /* Return the number of scatter-gather list elements required */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1040) static unsigned int sg_count_fuse_req(struct fuse_req *req)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1041) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1042) struct fuse_args *args = req->args;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1043) struct fuse_args_pages *ap = container_of(args, typeof(*ap), args);
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1044) unsigned int size, total_sgs = 1 /* fuse_in_header */;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1045)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1046) if (args->in_numargs - args->in_pages)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1047) total_sgs += 1;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1048)
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1049) if (args->in_pages) {
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1050) size = args->in_args[args->in_numargs - 1].size;
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1051) total_sgs += sg_count_fuse_pages(ap->descs, ap->num_pages,
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1052) size);
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1053) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1054)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1055) if (!test_bit(FR_ISREPLY, &req->flags))
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1056) return total_sgs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1057)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1058) total_sgs += 1 /* fuse_out_header */;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1059)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1060) if (args->out_numargs - args->out_pages)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1061) total_sgs += 1;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1062)
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1063) if (args->out_pages) {
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1064) size = args->out_args[args->out_numargs - 1].size;
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1065) total_sgs += sg_count_fuse_pages(ap->descs, ap->num_pages,
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1066) size);
42d3e2d041f08 (Vivek Goyal 2020-10-06 14:53:06 -0400 1067) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1068)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1069) return total_sgs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1070) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1071)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1072) /* Add pages to scatter-gather list and return number of elements used */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1073) static unsigned int sg_init_fuse_pages(struct scatterlist *sg,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1074) struct page **pages,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1075) struct fuse_page_desc *page_descs,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1076) unsigned int num_pages,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1077) unsigned int total_len)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1078) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1079) unsigned int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1080) unsigned int this_len;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1081)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1082) for (i = 0; i < num_pages && total_len; i++) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1083) sg_init_table(&sg[i], 1);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1084) this_len = min(page_descs[i].length, total_len);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1085) sg_set_page(&sg[i], pages[i], this_len, page_descs[i].offset);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1086) total_len -= this_len;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1087) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1088)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1089) return i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1090) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1091)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1092) /* Add args to scatter-gather list and return number of elements used */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1093) static unsigned int sg_init_fuse_args(struct scatterlist *sg,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1094) struct fuse_req *req,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1095) struct fuse_arg *args,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1096) unsigned int numargs,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1097) bool argpages,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1098) void *argbuf,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1099) unsigned int *len_used)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1100) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1101) struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1102) unsigned int total_sgs = 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1103) unsigned int len;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1104)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1105) len = fuse_len_args(numargs - argpages, args);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1106) if (len)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1107) sg_init_one(&sg[total_sgs++], argbuf, len);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1108)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1109) if (argpages)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1110) total_sgs += sg_init_fuse_pages(&sg[total_sgs],
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1111) ap->pages, ap->descs,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1112) ap->num_pages,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1113) args[numargs - 1].size);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1114)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1115) if (len_used)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1116) *len_used = len;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1117)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1118) return total_sgs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1119) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1120)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1121) /* Add a request to a virtqueue and kick the device */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1122) static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1123) struct fuse_req *req, bool in_flight)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1124) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1125) /* requests need at least 4 elements */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1126) struct scatterlist *stack_sgs[6];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1127) struct scatterlist stack_sg[ARRAY_SIZE(stack_sgs)];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1128) struct scatterlist **sgs = stack_sgs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1129) struct scatterlist *sg = stack_sg;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1130) struct virtqueue *vq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1131) struct fuse_args *args = req->args;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1132) unsigned int argbuf_used = 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1133) unsigned int out_sgs = 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1134) unsigned int in_sgs = 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1135) unsigned int total_sgs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1136) unsigned int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1137) int ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1138) bool notify;
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1139) struct fuse_pqueue *fpq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1140)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1141) /* Does the sglist fit on the stack? */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1142) total_sgs = sg_count_fuse_req(req);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1143) if (total_sgs > ARRAY_SIZE(stack_sgs)) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1144) sgs = kmalloc_array(total_sgs, sizeof(sgs[0]), GFP_ATOMIC);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1145) sg = kmalloc_array(total_sgs, sizeof(sg[0]), GFP_ATOMIC);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1146) if (!sgs || !sg) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1147) ret = -ENOMEM;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1148) goto out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1149) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1150) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1151)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1152) /* Use a bounce buffer since stack args cannot be mapped */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1153) ret = copy_args_to_argbuf(req);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1154) if (ret < 0)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1155) goto out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1156)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1157) /* Request elements */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1158) sg_init_one(&sg[out_sgs++], &req->in.h, sizeof(req->in.h));
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1159) out_sgs += sg_init_fuse_args(&sg[out_sgs], req,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1160) (struct fuse_arg *)args->in_args,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1161) args->in_numargs, args->in_pages,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1162) req->argbuf, &argbuf_used);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1163)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1164) /* Reply elements */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1165) if (test_bit(FR_ISREPLY, &req->flags)) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1166) sg_init_one(&sg[out_sgs + in_sgs++],
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1167) &req->out.h, sizeof(req->out.h));
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1168) in_sgs += sg_init_fuse_args(&sg[out_sgs + in_sgs], req,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1169) args->out_args, args->out_numargs,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1170) args->out_pages,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1171) req->argbuf + argbuf_used, NULL);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1172) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1173)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1174) WARN_ON(out_sgs + in_sgs != total_sgs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1175)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1176) for (i = 0; i < total_sgs; i++)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1177) sgs[i] = &sg[i];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1178)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1179) spin_lock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1180)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1181) if (!fsvq->connected) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1182) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1183) ret = -ENOTCONN;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1184) goto out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1185) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1186)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1187) vq = fsvq->vq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1188) ret = virtqueue_add_sgs(vq, sgs, out_sgs, in_sgs, req, GFP_ATOMIC);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1189) if (ret < 0) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1190) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1191) goto out;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1192) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1193)
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1194) /* Request successfully sent. */
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1195) fpq = &fsvq->fud->pq;
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1196) spin_lock(&fpq->lock);
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1197) list_add_tail(&req->list, fpq->processing);
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1198) spin_unlock(&fpq->lock);
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1199) set_bit(FR_SENT, &req->flags);
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1200) /* matches barrier in request_wait_answer() */
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1201) smp_mb__after_atomic();
5dbe190f34120 (Vivek Goyal 2019-10-15 13:46:24 -0400 1202)
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1203) if (!in_flight)
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1204) inc_in_flight_req(fsvq);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1205) notify = virtqueue_kick_prepare(vq);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1206)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1207) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1208)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1209) if (notify)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1210) virtqueue_notify(vq);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1211)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1212) out:
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1213) if (ret < 0 && req->argbuf) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1214) kfree(req->argbuf);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1215) req->argbuf = NULL;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1216) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1217) if (sgs != stack_sgs) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1218) kfree(sgs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1219) kfree(sg);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1220) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1221)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1222) return ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1223) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1224)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1225) static void virtio_fs_wake_pending_and_unlock(struct fuse_iqueue *fiq)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1226) __releases(fiq->lock)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1227) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1228) unsigned int queue_id = VQ_REQUEST; /* TODO multiqueue */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1229) struct virtio_fs *fs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1230) struct fuse_req *req;
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 1231) struct virtio_fs_vq *fsvq;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1232) int ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1233)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1234) WARN_ON(list_empty(&fiq->pending));
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1235) req = list_last_entry(&fiq->pending, struct fuse_req, list);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1236) clear_bit(FR_PENDING, &req->flags);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1237) list_del_init(&req->list);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1238) WARN_ON(!list_empty(&fiq->pending));
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1239) spin_unlock(&fiq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1240)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1241) fs = fiq->priv;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1242)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1243) pr_debug("%s: opcode %u unique %#llx nodeid %#llx in.len %u out.len %u\n",
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1244) __func__, req->in.h.opcode, req->in.h.unique,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1245) req->in.h.nodeid, req->in.h.len,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1246) fuse_len_args(req->args->out_numargs, req->args->out_args));
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1247)
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 1248) fsvq = &fs->vqs[queue_id];
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1249) ret = virtio_fs_enqueue_req(fsvq, req, false);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1250) if (ret < 0) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1251) if (ret == -ENOMEM || ret == -ENOSPC) {
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1252) /*
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1253) * Virtqueue full. Retry submission from worker
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1254) * context as we might be holding fc->bg_lock.
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1255) */
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1256) spin_lock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1257) list_add_tail(&req->list, &fsvq->queued_reqs);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1258) inc_in_flight_req(fsvq);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1259) schedule_delayed_work(&fsvq->dispatch_work,
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1260) msecs_to_jiffies(1));
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1261) spin_unlock(&fsvq->lock);
a9bfd9dd34175 (Vivek Goyal 2019-10-15 13:46:26 -0400 1262) return;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1263) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1264) req->out.h.error = ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1265) pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", ret);
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 1266)
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 1267) /* Can't end request in submission context. Use a worker */
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 1268) spin_lock(&fsvq->lock);
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 1269) list_add_tail(&req->list, &fsvq->end_reqs);
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 1270) schedule_delayed_work(&fsvq->dispatch_work, 0);
51fecdd2555b3 (Vivek Goyal 2019-10-15 13:46:22 -0400 1271) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1272) return;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1273) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1274) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1275)
00929447f5758 (YueHaibing 2019-11-11 20:23:59 +0800 1276) static const struct fuse_iqueue_ops virtio_fs_fiq_ops = {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1277) .wake_forget_and_unlock = virtio_fs_wake_forget_and_unlock,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1278) .wake_interrupt_and_unlock = virtio_fs_wake_interrupt_and_unlock,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1279) .wake_pending_and_unlock = virtio_fs_wake_pending_and_unlock,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1280) .release = virtio_fs_fiq_release,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1281) };
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1282)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1283) static inline void virtio_fs_ctx_set_defaults(struct fuse_fs_context *ctx)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1284) {
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1285) ctx->rootmode = S_IFDIR;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1286) ctx->default_permissions = 1;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1287) ctx->allow_other = 1;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1288) ctx->max_read = UINT_MAX;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1289) ctx->blksize = 512;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1290) ctx->destroy = true;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1291) ctx->no_control = true;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1292) ctx->no_force_umount = true;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1293) }
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1294)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1295) static int virtio_fs_fill_super(struct super_block *sb, struct fs_context *fsc)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1296) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1297) struct fuse_mount *fm = get_fuse_mount_super(sb);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1298) struct fuse_conn *fc = fm->fc;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1299) struct virtio_fs *fs = fc->iq.priv;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1300) struct fuse_fs_context *ctx = fsc->fs_private;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1301) unsigned int i;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1302) int err;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1303)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1304) virtio_fs_ctx_set_defaults(ctx);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1305) mutex_lock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1306)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1307) /* After holding mutex, make sure virtiofs device is still there.
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1308) * Though we are holding a reference to it, drive ->remove might
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1309) * still have cleaned up virtual queues. In that case bail out.
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1310) */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1311) err = -EINVAL;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1312) if (list_empty(&fs->list)) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1313) pr_info("virtio-fs: tag <%s> not found\n", fs->tag);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1314) goto err;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1315) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1316)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1317) err = -ENOMEM;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1318) /* Allocate fuse_dev for hiprio and notification queues */
7fd3abfa8dd7c (Vivek Goyal 2020-05-04 14:33:15 -0400 1319) for (i = 0; i < fs->nvqs; i++) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1320) struct virtio_fs_vq *fsvq = &fs->vqs[i];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1321)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1322) fsvq->fud = fuse_dev_alloc();
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1323) if (!fsvq->fud)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1324) goto err_free_fuse_devs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1325) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1326)
7fd3abfa8dd7c (Vivek Goyal 2020-05-04 14:33:15 -0400 1327) /* virtiofs allocates and installs its own fuse devices */
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1328) ctx->fudptr = NULL;
3f9b9efd82a84 (Vivek Goyal 2021-02-09 17:47:54 -0500 1329) if (ctx->dax) {
3f9b9efd82a84 (Vivek Goyal 2021-02-09 17:47:54 -0500 1330) if (!fs->dax_dev) {
3f9b9efd82a84 (Vivek Goyal 2021-02-09 17:47:54 -0500 1331) err = -EINVAL;
3f9b9efd82a84 (Vivek Goyal 2021-02-09 17:47:54 -0500 1332) pr_err("virtio-fs: dax can't be enabled as filesystem"
3f9b9efd82a84 (Vivek Goyal 2021-02-09 17:47:54 -0500 1333) " device does not support it.\n");
3f9b9efd82a84 (Vivek Goyal 2021-02-09 17:47:54 -0500 1334) goto err_free_fuse_devs;
3f9b9efd82a84 (Vivek Goyal 2021-02-09 17:47:54 -0500 1335) }
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1336) ctx->dax_dev = fs->dax_dev;
3f9b9efd82a84 (Vivek Goyal 2021-02-09 17:47:54 -0500 1337) }
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1338) err = fuse_fill_super_common(sb, ctx);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1339) if (err < 0)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1340) goto err_free_fuse_devs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1341)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1342) for (i = 0; i < fs->nvqs; i++) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1343) struct virtio_fs_vq *fsvq = &fs->vqs[i];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1344)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1345) fuse_dev_install(fsvq->fud, fc);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1346) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1347)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1348) /* Previous unmount will stop all queues. Start these again */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1349) virtio_fs_start_all_queues(fs);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1350) fuse_send_init(fm);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1351) mutex_unlock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1352) return 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1353)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1354) err_free_fuse_devs:
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1355) virtio_fs_free_devs(fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1356) err:
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1357) mutex_unlock(&virtio_fs_mutex);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1358) return err;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1359) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1360)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1361) static void virtio_fs_conn_destroy(struct fuse_mount *fm)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1362) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1363) struct fuse_conn *fc = fm->fc;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1364) struct virtio_fs *vfs = fc->iq.priv;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1365) struct virtio_fs_vq *fsvq = &vfs->vqs[VQ_HIPRIO];
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1366)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1367) /* Stop dax worker. Soon evict_inodes() will be called which
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1368) * will free all memory ranges belonging to all inodes.
9a752d18c85ae (Vivek Goyal 2020-08-19 18:19:56 -0400 1369) */
9a752d18c85ae (Vivek Goyal 2020-08-19 18:19:56 -0400 1370) if (IS_ENABLED(CONFIG_FUSE_DAX))
9a752d18c85ae (Vivek Goyal 2020-08-19 18:19:56 -0400 1371) fuse_dax_cancel_work(fc);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1372)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1373) /* Stop forget queue. Soon destroy will be sent */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1374) spin_lock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1375) fsvq->connected = false;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1376) spin_unlock(&fsvq->lock);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1377) virtio_fs_drain_all_queues(vfs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1378)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1379) fuse_conn_destroy(fm);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1380)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1381) /* fuse_conn_destroy() must have sent destroy. Stop all queues
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1382) * and drain one more time and free fuse devices. Freeing fuse
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1383) * devices will drop their reference on fuse_conn and that in
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1384) * turn will drop its reference on virtio_fs object.
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1385) */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1386) virtio_fs_stop_all_queues(vfs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1387) virtio_fs_drain_all_queues(vfs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1388) virtio_fs_free_devs(vfs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1389) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1390)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1391) static void virtio_kill_sb(struct super_block *sb)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1392) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1393) struct fuse_mount *fm = get_fuse_mount_super(sb);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1394) bool last;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1395)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1396) /* If mount failed, we can still be called without any fc */
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1397) if (fm) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1398) last = fuse_mount_remove(fm);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1399) if (last)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1400) virtio_fs_conn_destroy(fm);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1401) }
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1402) kill_anon_super(sb);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1403) }
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1404)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1405) static int virtio_fs_test_super(struct super_block *sb,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1406) struct fs_context *fsc)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1407) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1408) struct fuse_mount *fsc_fm = fsc->s_fs_info;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1409) struct fuse_mount *sb_fm = get_fuse_mount_super(sb);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1410)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1411) return fsc_fm->fc->iq.priv == sb_fm->fc->iq.priv;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1412) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1413)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1414) static int virtio_fs_get_tree(struct fs_context *fsc)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1415) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1416) struct virtio_fs *fs;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1417) struct super_block *sb;
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1418) struct fuse_conn *fc = NULL;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1419) struct fuse_mount *fm;
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1420) unsigned int virtqueue_size;
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1421) int err = -EIO;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1422)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1423) /* This gets a reference on virtio_fs object. This ptr gets installed
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1424) * in fc->iq->priv. Once fuse_conn is going away, it calls ->put()
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1425) * to drop the reference to this object.
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1426) */
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1427) fs = virtio_fs_find_instance(fsc->source);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1428) if (!fs) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1429) pr_info("virtio-fs: tag <%s> not found\n", fsc->source);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1430) return -EINVAL;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1431) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1432)
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1433) virtqueue_size = virtqueue_get_vring_size(fs->vqs[VQ_REQUEST].vq);
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1434) if (WARN_ON(virtqueue_size <= FUSE_HEADER_OVERHEAD))
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1435) goto out_err;
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1436)
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1437) err = -ENOMEM;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1438) fc = kzalloc(sizeof(struct fuse_conn), GFP_KERNEL);
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1439) if (!fc)
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1440) goto out_err;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1441)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1442) fm = kzalloc(sizeof(struct fuse_mount), GFP_KERNEL);
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1443) if (!fm)
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1444) goto out_err;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1445)
0a7419c68a45d (Miklos Szeredi 2021-04-14 10:40:58 +0200 1446) fuse_conn_init(fc, fm, fsc->user_ns, &virtio_fs_fiq_ops, fs);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1447) fc->release = fuse_free_conn;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1448) fc->delete_stale = true;
bf109c64040f5 (Max Reitz 2020-04-21 14:47:15 +0200 1449) fc->auto_submounts = true;
6ba041fc3c441 (Greg Kurz 2021-05-20 17:46:54 +0200 1450) fc->sync_fs = true;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1451)
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1452) /* Tell FUSE to split requests that exceed the virtqueue's size */
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1453) fc->max_pages_limit = min_t(unsigned int, fc->max_pages_limit,
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1454) virtqueue_size - FUSE_HEADER_OVERHEAD);
a7f0d7aab0b4f (Connor Kuehl 2021-03-18 08:52:22 -0500 1455)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1456) fsc->s_fs_info = fm;
b19d3d00d662c (Miklos Szeredi 2020-11-11 17:22:31 +0100 1457) sb = sget_fc(fsc, virtio_fs_test_super, set_anon_super_fc);
514b5e3ff45e6 (Miklos Szeredi 2020-11-11 17:22:32 +0100 1458) if (fsc->s_fs_info) {
514b5e3ff45e6 (Miklos Szeredi 2020-11-11 17:22:32 +0100 1459) fuse_conn_put(fc);
514b5e3ff45e6 (Miklos Szeredi 2020-11-11 17:22:32 +0100 1460) kfree(fm);
514b5e3ff45e6 (Miklos Szeredi 2020-11-11 17:22:32 +0100 1461) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1462) if (IS_ERR(sb))
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1463) return PTR_ERR(sb);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1464)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1465) if (!sb->s_root) {
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1466) err = virtio_fs_fill_super(sb, fsc);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1467) if (err) {
514b5e3ff45e6 (Miklos Szeredi 2020-11-11 17:22:32 +0100 1468) fuse_conn_put(fc);
514b5e3ff45e6 (Miklos Szeredi 2020-11-11 17:22:32 +0100 1469) kfree(fm);
66ab33bf6d434 (Miklos Szeredi 2020-11-11 17:22:31 +0100 1470) sb->s_fs_info = NULL;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1471) deactivate_locked_super(sb);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1472) return err;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1473) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1474)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1475) sb->s_flags |= SB_ACTIVE;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1476) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1477)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1478) WARN_ON(fsc->root);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1479) fsc->root = dget(sb->s_root);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1480) return 0;
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1481)
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1482) out_err:
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1483) kfree(fc);
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1484) mutex_lock(&virtio_fs_mutex);
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1485) virtio_fs_put(fs);
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1486) mutex_unlock(&virtio_fs_mutex);
833c5a42e28be (Miklos Szeredi 2020-11-11 17:22:32 +0100 1487) return err;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1488) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1489)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1490) static const struct fs_context_operations virtio_fs_context_ops = {
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1491) .free = virtio_fs_free_fc,
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1492) .parse_param = virtio_fs_parse_param,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1493) .get_tree = virtio_fs_get_tree,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1494) };
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1495)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1496) static int virtio_fs_init_fs_context(struct fs_context *fsc)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1497) {
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1498) struct fuse_fs_context *ctx;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1499)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1500) ctx = kzalloc(sizeof(struct fuse_fs_context), GFP_KERNEL);
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1501) if (!ctx)
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1502) return -ENOMEM;
1dd539577c42b (Vivek Goyal 2020-08-19 18:19:47 -0400 1503) fsc->fs_private = ctx;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1504) fsc->ops = &virtio_fs_context_ops;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1505) return 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1506) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1507)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1508) static struct file_system_type virtio_fs_type = {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1509) .owner = THIS_MODULE,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1510) .name = "virtiofs",
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1511) .init_fs_context = virtio_fs_init_fs_context,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1512) .kill_sb = virtio_kill_sb,
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1513) };
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1514)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1515) static int __init virtio_fs_init(void)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1516) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1517) int ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1518)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1519) ret = register_virtio_driver(&virtio_fs_driver);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1520) if (ret < 0)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1521) return ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1522)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1523) ret = register_filesystem(&virtio_fs_type);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1524) if (ret < 0) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1525) unregister_virtio_driver(&virtio_fs_driver);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1526) return ret;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1527) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1528)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1529) return 0;
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1530) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1531) module_init(virtio_fs_init);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1532)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1533) static void __exit virtio_fs_exit(void)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1534) {
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1535) unregister_filesystem(&virtio_fs_type);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1536) unregister_virtio_driver(&virtio_fs_driver);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1537) }
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1538) module_exit(virtio_fs_exit);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1539)
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1540) MODULE_AUTHOR("Stefan Hajnoczi <stefanha@redhat.com>");
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1541) MODULE_DESCRIPTION("Virtio Filesystem");
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1542) MODULE_LICENSE("GPL");
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1543) MODULE_ALIAS_FS(KBUILD_MODNAME);
a62a8ef9d97da (Stefan Hajnoczi 2018-06-12 09:41:17 +0100 1544) MODULE_DEVICE_TABLE(virtio, id_table);