virtio_fs.c (1efcf39eb627573f8d543ea396cf36b0651b1e56) virtio_fs.c (724c15a43e2c7ac26e2d07abef99191162498fa9)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * virtio-fs: Virtio Filesystem
4 * Copyright (C) 2018 Red Hat, Inc.
5 */
6
7#include <linux/fs.h>
8#include <linux/module.h>

--- 21 unchanged lines hidden (view full) ---

30 struct virtqueue *vq; /* protected by ->lock */
31 struct work_struct done_work;
32 struct list_head queued_reqs;
33 struct list_head end_reqs; /* End these requests */
34 struct delayed_work dispatch_work;
35 struct fuse_dev *fud;
36 bool connected;
37 long in_flight;
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * virtio-fs: Virtio Filesystem
4 * Copyright (C) 2018 Red Hat, Inc.
5 */
6
7#include <linux/fs.h>
8#include <linux/module.h>

--- 21 unchanged lines hidden (view full) ---

30 struct virtqueue *vq; /* protected by ->lock */
31 struct work_struct done_work;
32 struct list_head queued_reqs;
33 struct list_head end_reqs; /* End these requests */
34 struct delayed_work dispatch_work;
35 struct fuse_dev *fud;
36 bool connected;
37 long in_flight;
38 struct completion in_flight_zero; /* No inflight requests */
38 char name[24];
39} ____cacheline_aligned_in_smp;
40
41/* A virtio-fs device instance */
42struct virtio_fs {
43 struct kref refcount;
44 struct list_head list; /* on virtio_fs_instances */
45 char *tag;

--- 34 unchanged lines hidden (view full) ---

80 fsvq->in_flight++;
81}
82
83/* Should be called with fsvq->lock held. */
84static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
85{
86 WARN_ON(fsvq->in_flight <= 0);
87 fsvq->in_flight--;
39 char name[24];
40} ____cacheline_aligned_in_smp;
41
42/* A virtio-fs device instance */
43struct virtio_fs {
44 struct kref refcount;
45 struct list_head list; /* on virtio_fs_instances */
46 char *tag;

--- 34 unchanged lines hidden (view full) ---

81 fsvq->in_flight++;
82}
83
84/* Should be called with fsvq->lock held. */
85static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
86{
87 WARN_ON(fsvq->in_flight <= 0);
88 fsvq->in_flight--;
89 if (!fsvq->in_flight)
90 complete(&fsvq->in_flight_zero);
88}
89
90static void release_virtio_fs_obj(struct kref *ref)
91{
92 struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
93
94 kfree(vfs->vqs);
95 kfree(vfs);

--- 14 unchanged lines hidden (view full) ---

110 mutex_unlock(&virtio_fs_mutex);
111}
112
113static void virtio_fs_drain_queue(struct virtio_fs_vq *fsvq)
114{
115 WARN_ON(fsvq->in_flight < 0);
116
117 /* Wait for in flight requests to finish.*/
91}
92
93static void release_virtio_fs_obj(struct kref *ref)
94{
95 struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
96
97 kfree(vfs->vqs);
98 kfree(vfs);

--- 14 unchanged lines hidden (view full) ---

113 mutex_unlock(&virtio_fs_mutex);
114}
115
116static void virtio_fs_drain_queue(struct virtio_fs_vq *fsvq)
117{
118 WARN_ON(fsvq->in_flight < 0);
119
120 /* Wait for in flight requests to finish.*/
118 while (1) {
119 spin_lock(&fsvq->lock);
120 if (!fsvq->in_flight) {
121 spin_unlock(&fsvq->lock);
122 break;
123 }
121 spin_lock(&fsvq->lock);
122 if (fsvq->in_flight) {
123 /* We are holding virtio_fs_mutex. There should not be any
124 * waiters waiting for completion.
125 */
126 reinit_completion(&fsvq->in_flight_zero);
124 spin_unlock(&fsvq->lock);
127 spin_unlock(&fsvq->lock);
125 /* TODO use completion instead of timeout */
126 usleep_range(1000, 2000);
128 wait_for_completion(&fsvq->in_flight_zero);
129 } else {
130 spin_unlock(&fsvq->lock);
127 }
128
129 flush_work(&fsvq->done_work);
130 flush_delayed_work(&fsvq->dispatch_work);
131}
132
131 }
132
133 flush_work(&fsvq->done_work);
134 flush_delayed_work(&fsvq->dispatch_work);
135}
136
133static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
137static void virtio_fs_drain_all_queues_locked(struct virtio_fs *fs)
134{
135 struct virtio_fs_vq *fsvq;
136 int i;
137
138 for (i = 0; i < fs->nvqs; i++) {
139 fsvq = &fs->vqs[i];
140 virtio_fs_drain_queue(fsvq);
141 }
142}
143
138{
139 struct virtio_fs_vq *fsvq;
140 int i;
141
142 for (i = 0; i < fs->nvqs; i++) {
143 fsvq = &fs->vqs[i];
144 virtio_fs_drain_queue(fsvq);
145 }
146}
147
148static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
149{
150 /* Provides mutual exclusion between ->remove and ->kill_sb
151 * paths. We don't want both of these draining queue at the
152 * same time. Current completion logic reinits completion
153 * and that means there should not be any other thread
154 * doing reinit or waiting for completion already.
155 */
156 mutex_lock(&virtio_fs_mutex);
157 virtio_fs_drain_all_queues_locked(fs);
158 mutex_unlock(&virtio_fs_mutex);
159}
160
144static void virtio_fs_start_all_queues(struct virtio_fs *fs)
145{
146 struct virtio_fs_vq *fsvq;
147 int i;
148
149 for (i = 0; i < fs->nvqs; i++) {
150 fsvq = &fs->vqs[i];
151 spin_lock(&fsvq->lock);

--- 424 unchanged lines hidden (view full) ---

576 snprintf(fs->vqs[VQ_HIPRIO].name, sizeof(fs->vqs[VQ_HIPRIO].name),
577 "hiprio");
578 names[VQ_HIPRIO] = fs->vqs[VQ_HIPRIO].name;
579 INIT_WORK(&fs->vqs[VQ_HIPRIO].done_work, virtio_fs_hiprio_done_work);
580 INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].queued_reqs);
581 INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].end_reqs);
582 INIT_DELAYED_WORK(&fs->vqs[VQ_HIPRIO].dispatch_work,
583 virtio_fs_hiprio_dispatch_work);
161static void virtio_fs_start_all_queues(struct virtio_fs *fs)
162{
163 struct virtio_fs_vq *fsvq;
164 int i;
165
166 for (i = 0; i < fs->nvqs; i++) {
167 fsvq = &fs->vqs[i];
168 spin_lock(&fsvq->lock);

--- 424 unchanged lines hidden (view full) ---

593 snprintf(fs->vqs[VQ_HIPRIO].name, sizeof(fs->vqs[VQ_HIPRIO].name),
594 "hiprio");
595 names[VQ_HIPRIO] = fs->vqs[VQ_HIPRIO].name;
596 INIT_WORK(&fs->vqs[VQ_HIPRIO].done_work, virtio_fs_hiprio_done_work);
597 INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].queued_reqs);
598 INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].end_reqs);
599 INIT_DELAYED_WORK(&fs->vqs[VQ_HIPRIO].dispatch_work,
600 virtio_fs_hiprio_dispatch_work);
601 init_completion(&fs->vqs[VQ_HIPRIO].in_flight_zero);
584 spin_lock_init(&fs->vqs[VQ_HIPRIO].lock);
585
586 /* Initialize the requests virtqueues */
587 for (i = VQ_REQUEST; i < fs->nvqs; i++) {
588 spin_lock_init(&fs->vqs[i].lock);
589 INIT_WORK(&fs->vqs[i].done_work, virtio_fs_requests_done_work);
590 INIT_DELAYED_WORK(&fs->vqs[i].dispatch_work,
591 virtio_fs_request_dispatch_work);
592 INIT_LIST_HEAD(&fs->vqs[i].queued_reqs);
593 INIT_LIST_HEAD(&fs->vqs[i].end_reqs);
602 spin_lock_init(&fs->vqs[VQ_HIPRIO].lock);
603
604 /* Initialize the requests virtqueues */
605 for (i = VQ_REQUEST; i < fs->nvqs; i++) {
606 spin_lock_init(&fs->vqs[i].lock);
607 INIT_WORK(&fs->vqs[i].done_work, virtio_fs_requests_done_work);
608 INIT_DELAYED_WORK(&fs->vqs[i].dispatch_work,
609 virtio_fs_request_dispatch_work);
610 INIT_LIST_HEAD(&fs->vqs[i].queued_reqs);
611 INIT_LIST_HEAD(&fs->vqs[i].end_reqs);
612 init_completion(&fs->vqs[i].in_flight_zero);
594 snprintf(fs->vqs[i].name, sizeof(fs->vqs[i].name),
595 "requests.%u", i - VQ_REQUEST);
596 callbacks[i] = virtio_fs_vq_done;
597 names[i] = fs->vqs[i].name;
598 }
599
600 ret = virtio_find_vqs(vdev, fs->nvqs, vqs, callbacks, names, NULL);
601 if (ret < 0)

--- 77 unchanged lines hidden (view full) ---

679static void virtio_fs_remove(struct virtio_device *vdev)
680{
681 struct virtio_fs *fs = vdev->priv;
682
683 mutex_lock(&virtio_fs_mutex);
684 /* This device is going away. No one should get new reference */
685 list_del_init(&fs->list);
686 virtio_fs_stop_all_queues(fs);
613 snprintf(fs->vqs[i].name, sizeof(fs->vqs[i].name),
614 "requests.%u", i - VQ_REQUEST);
615 callbacks[i] = virtio_fs_vq_done;
616 names[i] = fs->vqs[i].name;
617 }
618
619 ret = virtio_find_vqs(vdev, fs->nvqs, vqs, callbacks, names, NULL);
620 if (ret < 0)

--- 77 unchanged lines hidden (view full) ---

698static void virtio_fs_remove(struct virtio_device *vdev)
699{
700 struct virtio_fs *fs = vdev->priv;
701
702 mutex_lock(&virtio_fs_mutex);
703 /* This device is going away. No one should get new reference */
704 list_del_init(&fs->list);
705 virtio_fs_stop_all_queues(fs);
687 virtio_fs_drain_all_queues(fs);
706 virtio_fs_drain_all_queues_locked(fs);
688 vdev->config->reset(vdev);
689 virtio_fs_cleanup_vqs(vdev, fs);
690
691 vdev->priv = NULL;
692 /* Put device reference on virtio_fs object */
693 virtio_fs_put(fs);
694 mutex_unlock(&virtio_fs_mutex);
695}

--- 540 unchanged lines hidden ---
707 vdev->config->reset(vdev);
708 virtio_fs_cleanup_vqs(vdev, fs);
709
710 vdev->priv = NULL;
711 /* Put device reference on virtio_fs object */
712 virtio_fs_put(fs);
713 mutex_unlock(&virtio_fs_mutex);
714}

--- 540 unchanged lines hidden ---