aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Zanussi <tzanussi@gmail.com>2008-08-06 00:05:03 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2008-08-20 11:15:23 -0700
commit435d30c6e982de6c1c4ec5727445657cdb3009ef (patch)
tree36acf4ad02b68359c04da044ece248e1c24d7bf4
parentcf6d7d728ac241a86939d1dcb89ad62ce9d8ce5d (diff)
relay: fix "full buffer with exactly full last subbuffer" accounting problem
commit 32194450330be327f3b25bf6b66298bd122599e9 upstream In relay's current read implementation, if the buffer is completely full but hasn't triggered the buffer-full condition (i.e. the last write didn't cross the subbuffer boundary) and the last subbuffer is exactly full, the subbuffer accounting code erroneously finds nothing available. This patch fixes the problem. Signed-off-by: Tom Zanussi <tzanussi@gmail.com> Cc: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> Cc: Pekka Enberg <penberg@cs.helsinki.fi> Cc: Jens Axboe <jens.axboe@oracle.com> Cc: Mathieu Desnoyers <compudj@krystal.dyndns.org> Cc: Andrea Righi <righi.andrea@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--kernel/relay.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/kernel/relay.c b/kernel/relay.c
index d6204a48581..ee2e614a344 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -803,6 +803,10 @@ static void relay_file_read_consume(struct rchan_buf *buf,
size_t n_subbufs = buf->chan->n_subbufs;
size_t read_subbuf;
+ if (buf->subbufs_produced == buf->subbufs_consumed &&
+ buf->offset == buf->bytes_consumed)
+ return;
+
if (buf->bytes_consumed + bytes_consumed > subbuf_size) {
relay_subbufs_consumed(buf->chan, buf->cpu, 1);
buf->bytes_consumed = 0;
@@ -834,6 +838,8 @@ static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
relay_file_read_consume(buf, read_pos, 0);
+ consumed = buf->subbufs_consumed;
+
if (unlikely(buf->offset > subbuf_size)) {
if (produced == consumed)
return 0;
@@ -852,8 +858,12 @@ static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
if (consumed > produced)
produced += n_subbufs * subbuf_size;
- if (consumed == produced)
+ if (consumed == produced) {
+ if (buf->offset == subbuf_size &&
+ buf->subbufs_produced > buf->subbufs_consumed)
+ return 1;
return 0;
+ }
return 1;
}