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 --- |