Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1923

kernel-2.6.18-238.el5.src.rpm

From: Masami Hiramatsu <mhiramat@redhat.com>
Date: Fri, 7 Sep 2007 15:47:46 -0400
Subject: [misc] Fix relay read start in overwrite mode
Message-id: 46E1AAE2.4060109@redhat.com
O-Subject: [RHEL5.2 PATCH 2/2] Fix relay read() start position in overwrite mode
Bugzilla: 250706

Hello,

This patch fixes a bug in the relay read interface causing the
number of consumed bytes to be set incorrectly on overwrite mode.

A relay file consists on several sub-buffers. These buffers are used
in sequence. If all buffers are filled with data and no buffers
are read, it stops writing to the buffer on normal(non-overwrite) mode.
On this mode, the difference between the number of consumed(read)
buffers and the number of produced(written) buffers are less than
the number of total sub-buffers.
However, the sub-buffers are cyclically used on overwrite mode.
This means, the difference between the number of consumed(read)
buffers and the number of produced(written) buffers could be more
than the number of total sub-buffers.
Since the relay miss-calculates the consumed buffers in this situation,
it drops some buffers which are never read.

To solve this problem, this patch fixes relay_file_read_avail() to
adjust the consumed buffers, and fixes relay_file_read_consume() to
calculate the read position based on the adjusted consumed buffers.

The original patch was merged into upstream kernel.
Commit:     a66e356c04ece4a96f44b942b68234c3de8ec3f5
http://www.mail-archive.com/git-commits-head@vger.kernel.org/msg14970.html

This patch can be applied for 2.6.18-44.el5 and resolves bz #250706.

Testing: I made a test script for this patch based on the method below,

http://www.uwsg.iu.edu/hypermail/linux/kernel/0706.2/1747.html

and tested it with the latest snapshot package of the systemtap.

( Since the systemtap package in RHEL5.1 is old and does not support
 overwrite mode yet, you need the latest snapshot which you can download from
 ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-20070901.tar.bz2
 for this test.)

Acked-by: Pete Zaitcev <zaitcev@redhat.com>
Acked-by: Josef Bacik <jbacik@redhat.com>

diff --git a/kernel/relay.c b/kernel/relay.c
index 026dee7..03fa02b 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -746,7 +746,10 @@ static void relay_file_read_consume(struct rchan_buf *buf,
 	}
 
 	buf->bytes_consumed += bytes_consumed;
-	read_subbuf = read_pos / buf->chan->subbuf_size;
+	if (!read_pos)
+		read_subbuf = buf->subbufs_consumed % n_subbufs;
+	else
+		read_subbuf = read_pos / buf->chan->subbuf_size;
 	if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) {
 		if ((read_subbuf == buf->subbufs_produced % n_subbufs) &&
 		    (buf->offset == subbuf_size))
@@ -775,8 +778,9 @@ static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
 	}
 
 	if (unlikely(produced - consumed >= n_subbufs)) {
-		consumed = (produced / n_subbufs) * n_subbufs;
+		consumed = produced - n_subbufs + 1;
 		buf->subbufs_consumed = consumed;
+		buf->bytes_consumed = 0;
 	}
 	
 	produced = (produced % n_subbufs) * subbuf_size + buf->offset;