* [PATCH 0/3] virtiofs: Small Cleanups for 5.5
@ 2019-10-30 15:07 Vivek Goyal
2019-10-30 15:07 ` [PATCH 1/3] virtiofs: Use a common function to send forget Vivek Goyal
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Vivek Goyal @ 2019-10-30 15:07 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, virtio-fs
Cc: virtualization, vgoyal, miklos, stefanha, dgilbert
Hi Miklos,
Here are few small cleanups for virtiofs for 5.5. I had received some
comments from Michael Tsirkin on original virtiofs patches and these
cleanups are result of these comments.
Thanks
Vivek
Vivek Goyal (3):
virtiofs: Use a common function to send forget
virtiofs: Do not send forget request "struct list_head" element
virtiofs: Use completions while waiting for queue to be drained
fs/fuse/virtio_fs.c | 204 ++++++++++++++++++++++----------------------
1 file changed, 103 insertions(+), 101 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/3] virtiofs: Use a common function to send forget
2019-10-30 15:07 [PATCH 0/3] virtiofs: Small Cleanups for 5.5 Vivek Goyal
@ 2019-10-30 15:07 ` Vivek Goyal
2019-10-30 15:07 ` [PATCH 2/3] virtiofs: Do not send forget request "struct list_head" element Vivek Goyal
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Vivek Goyal @ 2019-10-30 15:07 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, virtio-fs
Cc: virtualization, vgoyal, miklos, stefanha, dgilbert
Currently we are duplicating logic to send forgets at two places. Consolidate
the code by calling one helper function.
This also uses virtqueue_add_outbuf() instead of virtqueue_add_sgs(). Former
is simpler to call.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
fs/fuse/virtio_fs.c | 150 +++++++++++++++++++-------------------------
1 file changed, 63 insertions(+), 87 deletions(-)
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index a5c86048b96e..6cc7be170cb8 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -313,17 +313,71 @@ static void virtio_fs_request_dispatch_work(struct work_struct *work)
}
}
+/*
+ * Returns 1 if queue is full and sender should wait a bit before sending
+ * next request, 0 otherwise.
+ */
+static int send_forget_request(struct virtio_fs_vq *fsvq,
+ struct virtio_fs_forget *forget,
+ bool in_flight)
+{
+ struct scatterlist sg;
+ struct virtqueue *vq;
+ int ret = 0;
+ bool notify;
+
+ spin_lock(&fsvq->lock);
+ if (!fsvq->connected) {
+ if (in_flight)
+ dec_in_flight_req(fsvq);
+ kfree(forget);
+ goto out;
+ }
+
+ sg_init_one(&sg, forget, sizeof(*forget));
+ vq = fsvq->vq;
+ dev_dbg(&vq->vdev->dev, "%s\n", __func__);
+
+ ret = virtqueue_add_outbuf(vq, &sg, 1, forget, GFP_ATOMIC);
+ if (ret < 0) {
+ if (ret == -ENOMEM || ret == -ENOSPC) {
+ pr_debug("virtio-fs: Could not queue FORGET: err=%d."
+ " Will try later\n", ret);
+ list_add_tail(&forget->list, &fsvq->queued_reqs);
+ schedule_delayed_work(&fsvq->dispatch_work,
+ msecs_to_jiffies(1));
+ if (!in_flight)
+ inc_in_flight_req(fsvq);
+ /* Queue is full */
+ ret = 1;
+ } else {
+ pr_debug("virtio-fs: Could not queue FORGET: err=%d."
+ " Dropping it.\n", ret);
+ kfree(forget);
+ if (in_flight)
+ dec_in_flight_req(fsvq);
+ }
+ goto out;
+ }
+
+ if (!in_flight)
+ inc_in_flight_req(fsvq);
+ notify = virtqueue_kick_prepare(vq);
+ spin_unlock(&fsvq->lock);
+
+ if (notify)
+ virtqueue_notify(vq);
+ return ret;
+out:
+ spin_unlock(&fsvq->lock);
+ return ret;
+}
+
static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
{
struct virtio_fs_forget *forget;
struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
dispatch_work.work);
- struct virtqueue *vq = fsvq->vq;
- struct scatterlist sg;
- struct scatterlist *sgs[] = {&sg};
- bool notify;
- int ret;
-
pr_debug("virtio-fs: worker %s called.\n", __func__);
while (1) {
spin_lock(&fsvq->lock);
@@ -335,43 +389,9 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
}
list_del(&forget->list);
- if (!fsvq->connected) {
- dec_in_flight_req(fsvq);
- spin_unlock(&fsvq->lock);
- kfree(forget);
- continue;
- }
-
- sg_init_one(&sg, forget, sizeof(*forget));
-
- /* Enqueue the request */
- dev_dbg(&vq->vdev->dev, "%s\n", __func__);
- ret = virtqueue_add_sgs(vq, sgs, 1, 0, forget, GFP_ATOMIC);
- if (ret < 0) {
- if (ret == -ENOMEM || ret == -ENOSPC) {
- pr_debug("virtio-fs: Could not queue FORGET: err=%d. Will try later\n",
- ret);
- list_add_tail(&forget->list,
- &fsvq->queued_reqs);
- schedule_delayed_work(&fsvq->dispatch_work,
- msecs_to_jiffies(1));
- } else {
- pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
- ret);
- dec_in_flight_req(fsvq);
- kfree(forget);
- }
- spin_unlock(&fsvq->lock);
- return;
- }
-
- notify = virtqueue_kick_prepare(vq);
spin_unlock(&fsvq->lock);
-
- if (notify)
- virtqueue_notify(vq);
- pr_debug("virtio-fs: worker %s dispatched one forget request.\n",
- __func__);
+ if (send_forget_request(fsvq, forget, true))
+ return;
}
}
@@ -710,14 +730,9 @@ __releases(fiq->lock)
{
struct fuse_forget_link *link;
struct virtio_fs_forget *forget;
- struct scatterlist sg;
- struct scatterlist *sgs[] = {&sg};
struct virtio_fs *fs;
- struct virtqueue *vq;
struct virtio_fs_vq *fsvq;
- bool notify;
u64 unique;
- int ret;
link = fuse_dequeue_forget(fiq, 1, NULL);
unique = fuse_get_unique(fiq);
@@ -739,46 +754,7 @@ __releases(fiq->lock)
.nlookup = link->forget_one.nlookup,
};
- sg_init_one(&sg, forget, sizeof(*forget));
-
- /* Enqueue the request */
- spin_lock(&fsvq->lock);
-
- if (!fsvq->connected) {
- kfree(forget);
- spin_unlock(&fsvq->lock);
- goto out;
- }
-
- vq = fsvq->vq;
- dev_dbg(&vq->vdev->dev, "%s\n", __func__);
-
- ret = virtqueue_add_sgs(vq, sgs, 1, 0, forget, GFP_ATOMIC);
- if (ret < 0) {
- if (ret == -ENOMEM || ret == -ENOSPC) {
- pr_debug("virtio-fs: Could not queue FORGET: err=%d. Will try later.\n",
- ret);
- list_add_tail(&forget->list, &fsvq->queued_reqs);
- schedule_delayed_work(&fsvq->dispatch_work,
- msecs_to_jiffies(1));
- inc_in_flight_req(fsvq);
- } else {
- pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
- ret);
- kfree(forget);
- }
- spin_unlock(&fsvq->lock);
- goto out;
- }
-
- inc_in_flight_req(fsvq);
- notify = virtqueue_kick_prepare(vq);
-
- spin_unlock(&fsvq->lock);
-
- if (notify)
- virtqueue_notify(vq);
-out:
+ send_forget_request(fsvq, forget, false);
kfree(link);
}
--
2.20.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/3] virtiofs: Do not send forget request "struct list_head" element
2019-10-30 15:07 [PATCH 0/3] virtiofs: Small Cleanups for 5.5 Vivek Goyal
2019-10-30 15:07 ` [PATCH 1/3] virtiofs: Use a common function to send forget Vivek Goyal
@ 2019-10-30 15:07 ` Vivek Goyal
2019-11-13 14:30 ` Stefan Hajnoczi
2019-10-30 15:07 ` [PATCH 3/3] virtiofs: Use completions while waiting for queue to be drained Vivek Goyal
2019-11-13 14:40 ` [PATCH 0/3] virtiofs: Small Cleanups for 5.5 Stefan Hajnoczi
3 siblings, 1 reply; 7+ messages in thread
From: Vivek Goyal @ 2019-10-30 15:07 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, virtio-fs
Cc: virtualization, vgoyal, miklos, stefanha, dgilbert
We are sending whole of virtio_fs_foreget struct to the other end over
virtqueue. Other end does not need to see elements like "struct list".
That's internal detail of guest kernel. Fix it.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
fs/fuse/virtio_fs.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 6cc7be170cb8..43224db8d9ed 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -48,11 +48,15 @@ struct virtio_fs {
unsigned int num_request_queues; /* number of request queues */
};
-struct virtio_fs_forget {
+struct virtio_fs_forget_req {
struct fuse_in_header ih;
struct fuse_forget_in arg;
+};
+
+struct virtio_fs_forget {
/* This request can be temporarily queued on virt queue */
struct list_head list;
+ struct virtio_fs_forget_req req;
};
static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
@@ -325,6 +329,7 @@ static int send_forget_request(struct virtio_fs_vq *fsvq,
struct virtqueue *vq;
int ret = 0;
bool notify;
+ struct virtio_fs_forget_req *req = &forget->req;
spin_lock(&fsvq->lock);
if (!fsvq->connected) {
@@ -334,7 +339,7 @@ static int send_forget_request(struct virtio_fs_vq *fsvq,
goto out;
}
- sg_init_one(&sg, forget, sizeof(*forget));
+ sg_init_one(&sg, req, sizeof(*req));
vq = fsvq->vq;
dev_dbg(&vq->vdev->dev, "%s\n", __func__);
@@ -730,6 +735,7 @@ __releases(fiq->lock)
{
struct fuse_forget_link *link;
struct virtio_fs_forget *forget;
+ struct virtio_fs_forget_req *req;
struct virtio_fs *fs;
struct virtio_fs_vq *fsvq;
u64 unique;
@@ -743,14 +749,15 @@ __releases(fiq->lock)
/* Allocate a buffer for the request */
forget = kmalloc(sizeof(*forget), GFP_NOFS | __GFP_NOFAIL);
+ req = &forget->req;
- forget->ih = (struct fuse_in_header){
+ req->ih = (struct fuse_in_header){
.opcode = FUSE_FORGET,
.nodeid = link->forget_one.nodeid,
.unique = unique,
- .len = sizeof(*forget),
+ .len = sizeof(*req),
};
- forget->arg = (struct fuse_forget_in){
+ req->arg = (struct fuse_forget_in){
.nlookup = link->forget_one.nlookup,
};
--
2.20.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] virtiofs: Use completions while waiting for queue to be drained
2019-10-30 15:07 [PATCH 0/3] virtiofs: Small Cleanups for 5.5 Vivek Goyal
2019-10-30 15:07 ` [PATCH 1/3] virtiofs: Use a common function to send forget Vivek Goyal
2019-10-30 15:07 ` [PATCH 2/3] virtiofs: Do not send forget request "struct list_head" element Vivek Goyal
@ 2019-10-30 15:07 ` Vivek Goyal
2019-11-13 14:40 ` Stefan Hajnoczi
2019-11-13 14:40 ` [PATCH 0/3] virtiofs: Small Cleanups for 5.5 Stefan Hajnoczi
3 siblings, 1 reply; 7+ messages in thread
From: Vivek Goyal @ 2019-10-30 15:07 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, virtio-fs
Cc: virtualization, vgoyal, miklos, stefanha, dgilbert
While we wait for queue to finish draining, use completions instead of
uslee_range(). This is better way of waiting for event.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
fs/fuse/virtio_fs.c | 39 +++++++++++++++++++++++++++++----------
1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 43224db8d9ed..b5ba83ef1914 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -35,6 +35,7 @@ struct virtio_fs_vq {
struct fuse_dev *fud;
bool connected;
long in_flight;
+ struct completion in_flight_zero; /* No inflight requests */
char name[24];
} ____cacheline_aligned_in_smp;
@@ -85,6 +86,8 @@ static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
{
WARN_ON(fsvq->in_flight <= 0);
fsvq->in_flight--;
+ if (!fsvq->in_flight)
+ complete(&fsvq->in_flight_zero);
}
static void release_virtio_fs_obj(struct kref *ref)
@@ -115,22 +118,23 @@ static void virtio_fs_drain_queue(struct virtio_fs_vq *fsvq)
WARN_ON(fsvq->in_flight < 0);
/* Wait for in flight requests to finish.*/
- while (1) {
- spin_lock(&fsvq->lock);
- if (!fsvq->in_flight) {
- spin_unlock(&fsvq->lock);
- break;
- }
+ spin_lock(&fsvq->lock);
+ if (fsvq->in_flight) {
+ /* We are holding virtio_fs_mutex. There should not be any
+ * waiters waiting for completion.
+ */
+ reinit_completion(&fsvq->in_flight_zero);
+ spin_unlock(&fsvq->lock);
+ wait_for_completion(&fsvq->in_flight_zero);
+ } else {
spin_unlock(&fsvq->lock);
- /* TODO use completion instead of timeout */
- usleep_range(1000, 2000);
}
flush_work(&fsvq->done_work);
flush_delayed_work(&fsvq->dispatch_work);
}
-static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
+static void virtio_fs_drain_all_queues_locked(struct virtio_fs *fs)
{
struct virtio_fs_vq *fsvq;
int i;
@@ -141,6 +145,19 @@ static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
}
}
+static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
+{
+ /* Provides mutual exclusion between ->remove and ->kill_sb
+ * paths. We don't want both of these draining queue at the
+ * same time. Current completion logic reinits completion
+ * and that means there should not be any other thread
+ * doing reinit or waiting for completion already.
+ */
+ mutex_lock(&virtio_fs_mutex);
+ virtio_fs_drain_all_queues_locked(fs);
+ mutex_unlock(&virtio_fs_mutex);
+}
+
static void virtio_fs_start_all_queues(struct virtio_fs *fs)
{
struct virtio_fs_vq *fsvq;
@@ -581,6 +598,7 @@ static int virtio_fs_setup_vqs(struct virtio_device *vdev,
INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].end_reqs);
INIT_DELAYED_WORK(&fs->vqs[VQ_HIPRIO].dispatch_work,
virtio_fs_hiprio_dispatch_work);
+ init_completion(&fs->vqs[VQ_HIPRIO].in_flight_zero);
spin_lock_init(&fs->vqs[VQ_HIPRIO].lock);
/* Initialize the requests virtqueues */
@@ -591,6 +609,7 @@ static int virtio_fs_setup_vqs(struct virtio_device *vdev,
virtio_fs_request_dispatch_work);
INIT_LIST_HEAD(&fs->vqs[i].queued_reqs);
INIT_LIST_HEAD(&fs->vqs[i].end_reqs);
+ init_completion(&fs->vqs[i].in_flight_zero);
snprintf(fs->vqs[i].name, sizeof(fs->vqs[i].name),
"requests.%u", i - VQ_REQUEST);
callbacks[i] = virtio_fs_vq_done;
@@ -684,7 +703,7 @@ static void virtio_fs_remove(struct virtio_device *vdev)
/* This device is going away. No one should get new reference */
list_del_init(&fs->list);
virtio_fs_stop_all_queues(fs);
- virtio_fs_drain_all_queues(fs);
+ virtio_fs_drain_all_queues_locked(fs);
vdev->config->reset(vdev);
virtio_fs_cleanup_vqs(vdev, fs);
--
2.20.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] virtiofs: Do not send forget request "struct list_head" element
2019-10-30 15:07 ` [PATCH 2/3] virtiofs: Do not send forget request "struct list_head" element Vivek Goyal
@ 2019-11-13 14:30 ` Stefan Hajnoczi
0 siblings, 0 replies; 7+ messages in thread
From: Stefan Hajnoczi @ 2019-11-13 14:30 UTC (permalink / raw)
To: Vivek Goyal
Cc: linux-fsdevel, linux-kernel, virtio-fs, virtualization, miklos, dgilbert
[-- Attachment #1: Type: text/plain, Size: 153 bytes --]
On Wed, Oct 30, 2019 at 11:07:18AM -0400, Vivek Goyal wrote:
> We are sending whole of virtio_fs_foreget struct to the other end over
s/foreget/forget/
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] virtiofs: Use completions while waiting for queue to be drained
2019-10-30 15:07 ` [PATCH 3/3] virtiofs: Use completions while waiting for queue to be drained Vivek Goyal
@ 2019-11-13 14:40 ` Stefan Hajnoczi
0 siblings, 0 replies; 7+ messages in thread
From: Stefan Hajnoczi @ 2019-11-13 14:40 UTC (permalink / raw)
To: Vivek Goyal
Cc: linux-fsdevel, linux-kernel, virtio-fs, virtualization, miklos, dgilbert
[-- Attachment #1: Type: text/plain, Size: 225 bytes --]
On Wed, Oct 30, 2019 at 11:07:19AM -0400, Vivek Goyal wrote:
> While we wait for queue to finish draining, use completions instead of
> uslee_range(). This is better way of waiting for event.
s/uslee_range()/usleep_range()/
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/3] virtiofs: Small Cleanups for 5.5
2019-10-30 15:07 [PATCH 0/3] virtiofs: Small Cleanups for 5.5 Vivek Goyal
` (2 preceding siblings ...)
2019-10-30 15:07 ` [PATCH 3/3] virtiofs: Use completions while waiting for queue to be drained Vivek Goyal
@ 2019-11-13 14:40 ` Stefan Hajnoczi
3 siblings, 0 replies; 7+ messages in thread
From: Stefan Hajnoczi @ 2019-11-13 14:40 UTC (permalink / raw)
To: Vivek Goyal
Cc: linux-fsdevel, linux-kernel, virtio-fs, virtualization, miklos, dgilbert
[-- Attachment #1: Type: text/plain, Size: 789 bytes --]
On Wed, Oct 30, 2019 at 11:07:16AM -0400, Vivek Goyal wrote:
> Hi Miklos,
>
> Here are few small cleanups for virtiofs for 5.5. I had received some
> comments from Michael Tsirkin on original virtiofs patches and these
> cleanups are result of these comments.
>
> Thanks
> Vivek
>
> Vivek Goyal (3):
> virtiofs: Use a common function to send forget
> virtiofs: Do not send forget request "struct list_head" element
> virtiofs: Use completions while waiting for queue to be drained
>
> fs/fuse/virtio_fs.c | 204 ++++++++++++++++++++++----------------------
> 1 file changed, 103 insertions(+), 101 deletions(-)
>
> --
> 2.20.1
>
There are typos in the commit descriptions but the code looks fine:
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2019-11-13 14:40 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-30 15:07 [PATCH 0/3] virtiofs: Small Cleanups for 5.5 Vivek Goyal
2019-10-30 15:07 ` [PATCH 1/3] virtiofs: Use a common function to send forget Vivek Goyal
2019-10-30 15:07 ` [PATCH 2/3] virtiofs: Do not send forget request "struct list_head" element Vivek Goyal
2019-11-13 14:30 ` Stefan Hajnoczi
2019-10-30 15:07 ` [PATCH 3/3] virtiofs: Use completions while waiting for queue to be drained Vivek Goyal
2019-11-13 14:40 ` Stefan Hajnoczi
2019-11-13 14:40 ` [PATCH 0/3] virtiofs: Small Cleanups for 5.5 Stefan Hajnoczi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).