From: "K. Y. Srinivasan" <kys@microsoft.com>
To: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org,
devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com,
vkuznets@redhat.com, jasowang@redhat.com
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Subject: [PATCH 9/9] Drivers: hv: ring_buffer: eliminate hv_ringbuffer_peek()
Date: Mon, 14 Dec 2015 19:02:01 -0800 [thread overview]
Message-ID: <1450148521-28447-9-git-send-email-kys@microsoft.com> (raw)
In-Reply-To: <1450148521-28447-1-git-send-email-kys@microsoft.com>
From: Vitaly Kuznetsov <vkuznets@redhat.com>
Currently, there is only one user for hv_ringbuffer_read()/
hv_ringbuffer_peak() functions and the usage of these functions is:
- insecure as we drop ring_lock between them, someone else (in theory
only) can acquire it in between;
- non-optimal as we do a number of things (acquire/release the above
mentioned lock, calculate available space on the ring, ...) twice and
this path is performance-critical.
Remove hv_ringbuffer_peek() moving the logic from __vmbus_recvpacket() to
hv_ringbuffer_read().
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
drivers/hv/channel.c | 30 +-------------------
drivers/hv/hyperv_vmbus.h | 11 ++-----
drivers/hv/ring_buffer.c | 65 +++++++++++++++++++++++++-------------------
3 files changed, 42 insertions(+), 64 deletions(-)
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index dd6de7f..1161d68 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -927,37 +927,11 @@ __vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
u32 bufferlen, u32 *buffer_actual_len, u64 *requestid,
bool raw)
{
- struct vmpacket_descriptor desc;
- u32 packetlen;
- u32 userlen;
int ret;
bool signal = false;
- *buffer_actual_len = 0;
- *requestid = 0;
-
-
- ret = hv_ringbuffer_peek(&channel->inbound, &desc,
- sizeof(struct vmpacket_descriptor));
- if (ret != 0)
- return 0;
-
- packetlen = desc.len8 << 3;
- if (!raw)
- userlen = packetlen - (desc.offset8 << 3);
- else
- userlen = packetlen;
-
- *buffer_actual_len = userlen;
-
- if (userlen > bufferlen)
- return -ENOBUFS;
-
- *requestid = desc.trans_id;
-
- /* Copy over the packet to the user buffer */
- ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
- raw ? 0 : desc.offset8 << 3, &signal);
+ ret = hv_ringbuffer_read(&channel->inbound, buffer, bufferlen,
+ buffer_actual_len, requestid, &signal, raw);
if (signal)
vmbus_setevent(channel);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 4d67e98..0411b7b 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -619,14 +619,9 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
struct kvec *kv_list,
u32 kv_count, bool *signal);
-int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
- u32 buflen);
-
-int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info,
- void *buffer,
- u32 buflen,
- u32 offset, bool *signal);
-
+int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
+ void *buffer, u32 buflen, u32 *buffer_actual_len,
+ u64 *requestid, bool *signal, bool raw);
void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info);
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 07f9408..b53702c 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -380,30 +380,59 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
return 0;
}
-static inline int __hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
- void *buffer, u32 buflen, u32 offset,
- bool *signal, bool advance)
+int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
+ void *buffer, u32 buflen, u32 *buffer_actual_len,
+ u64 *requestid, bool *signal, bool raw)
{
u32 bytes_avail_towrite;
u32 bytes_avail_toread;
u32 next_read_location = 0;
u64 prev_indices = 0;
unsigned long flags;
+ struct vmpacket_descriptor desc;
+ u32 offset;
+ u32 packetlen;
+ int ret = 0;
if (buflen <= 0)
return -EINVAL;
spin_lock_irqsave(&inring_info->ring_lock, flags);
+ *buffer_actual_len = 0;
+ *requestid = 0;
+
hv_get_ringbuffer_availbytes(inring_info,
&bytes_avail_toread,
&bytes_avail_towrite);
/* Make sure there is something to read */
- if (bytes_avail_toread < buflen) {
- spin_unlock_irqrestore(&inring_info->ring_lock, flags);
+ if (bytes_avail_toread < sizeof(desc)) {
+ /*
+ * No error is set when there is even no header, drivers are
+ * supposed to analyze buffer_actual_len.
+ */
+ goto out_unlock;
+ }
- return -EAGAIN;
+ next_read_location = hv_get_next_read_location(inring_info);
+ next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc,
+ sizeof(desc),
+ next_read_location);
+
+ offset = raw ? 0 : (desc.offset8 << 3);
+ packetlen = (desc.len8 << 3) - offset;
+ *buffer_actual_len = packetlen;
+ *requestid = desc.trans_id;
+
+ if (bytes_avail_toread < packetlen + offset) {
+ ret = -EAGAIN;
+ goto out_unlock;
+ }
+
+ if (packetlen > buflen) {
+ ret = -ENOBUFS;
+ goto out_unlock;
}
next_read_location =
@@ -411,12 +440,9 @@ static inline int __hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
next_read_location = hv_copyfrom_ringbuffer(inring_info,
buffer,
- buflen,
+ packetlen,
next_read_location);
- if (!advance)
- goto out_unlock;
-
next_read_location = hv_copyfrom_ringbuffer(inring_info,
&prev_indices,
sizeof(u64),
@@ -436,22 +462,5 @@ static inline int __hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
out_unlock:
spin_unlock_irqrestore(&inring_info->ring_lock, flags);
- return 0;
-}
-
-/* Read from ring buffer without advancing the read index. */
-int hv_ringbuffer_peek(struct hv_ring_buffer_info *inring_info,
- void *buffer, u32 buflen)
-{
- return __hv_ringbuffer_read(inring_info, buffer, buflen,
- 0, NULL, false);
-}
-
-/* Read from ring buffer and advance the read index. */
-int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
- void *buffer, u32 buflen, u32 offset,
- bool *signal)
-{
- return __hv_ringbuffer_read(inring_info, buffer, buflen,
- offset, signal, true);
+ return ret;
}
--
1.7.4.1
prev parent reply other threads:[~2015-12-15 1:28 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-15 3:00 [PATCH 0/9] Drivers: hv: Cleanup ringbuffer code K. Y. Srinivasan
2015-12-15 3:01 ` [PATCH 1/9] Drivers: hv: utils: fix memory leak on on_msg() failure K. Y. Srinivasan
2015-12-15 3:01 ` [PATCH 2/9] Drivers: hv: utils: rename outmsg_lock K. Y. Srinivasan
2015-12-15 3:01 ` [PATCH 3/9] Drivers: hv: utils: introduce HVUTIL_TRANSPORT_DESTROY mode K. Y. Srinivasan
2015-12-15 12:14 ` Dexuan Cui
2015-12-15 17:10 ` Vitaly Kuznetsov
2015-12-15 3:01 ` [PATCH 4/9] Drivers: hv: utils: fix crash when device is removed from host side K. Y. Srinivasan
2015-12-15 3:01 ` [PATCH 5/9] Drivers: hv: ring_buffer.c: fix comment style K. Y. Srinivasan
2015-12-15 3:01 ` [PATCH 6/9] Drivers: hv: ring_buffer: remove stray smp_read_barrier_depends() K. Y. Srinivasan
2015-12-15 3:01 ` [PATCH 7/9] Drivers: hv: ring_buffer: remove code duplication from hv_ringbuffer_peek/read() K. Y. Srinivasan
2015-12-15 3:02 ` [PATCH 8/9] Drivers: hv: remove code duplication between vmbus_recvpacket()/vmbus_recvpacket_raw() K. Y. Srinivasan
2015-12-15 3:02 ` K. Y. Srinivasan [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1450148521-28447-9-git-send-email-kys@microsoft.com \
--to=kys@microsoft.com \
--cc=apw@canonical.com \
--cc=devel@linuxdriverproject.org \
--cc=gregkh@linuxfoundation.org \
--cc=jasowang@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=olaf@aepfle.de \
--cc=vkuznets@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.