Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kernel/relay.c: fix read_pos error when multiple readers

When reading, read_pos should start with bytes_consumed, not file->f_pos.
Because when there is more than one reader, the read_pos corresponding to
file->f_pos may have been consumed, which will cause the data that has
been consumed to be read and the bytes_consumed update error.

Signed-off-by: Pengcheng Yang <yangpc@wangsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jann Horn <jannh@google.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>e
Link: http://lkml.kernel.org/r/1579691175-28949-1-git-send-email-yangpc@wangsu.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Pengcheng Yang and committed by
Linus Torvalds
341a7213 54e200ab

+7 -10
+7 -10
kernel/relay.c
··· 996 996 /* 997 997 * relay_file_read_avail - boolean, are there unconsumed bytes available? 998 998 */ 999 - static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos) 999 + static int relay_file_read_avail(struct rchan_buf *buf) 1000 1000 { 1001 1001 size_t subbuf_size = buf->chan->subbuf_size; 1002 1002 size_t n_subbufs = buf->chan->n_subbufs; 1003 1003 size_t produced = buf->subbufs_produced; 1004 1004 size_t consumed = buf->subbufs_consumed; 1005 1005 1006 - relay_file_read_consume(buf, read_pos, 0); 1006 + relay_file_read_consume(buf, 0, 0); 1007 1007 1008 1008 consumed = buf->subbufs_consumed; 1009 1009 ··· 1064 1064 1065 1065 /** 1066 1066 * relay_file_read_start_pos - find the first available byte to read 1067 - * @read_pos: file read position 1068 1067 * @buf: relay channel buffer 1069 1068 * 1070 - * If the @read_pos is in the middle of padding, return the 1069 + * If the read_pos is in the middle of padding, return the 1071 1070 * position of the first actually available byte, otherwise 1072 1071 * return the original value. 1073 1072 */ 1074 - static size_t relay_file_read_start_pos(size_t read_pos, 1075 - struct rchan_buf *buf) 1073 + static size_t relay_file_read_start_pos(struct rchan_buf *buf) 1076 1074 { 1077 1075 size_t read_subbuf, padding, padding_start, padding_end; 1078 1076 size_t subbuf_size = buf->chan->subbuf_size; 1079 1077 size_t n_subbufs = buf->chan->n_subbufs; 1080 1078 size_t consumed = buf->subbufs_consumed % n_subbufs; 1079 + size_t read_pos = consumed * subbuf_size + buf->bytes_consumed; 1081 1080 1082 - if (!read_pos) 1083 - read_pos = consumed * subbuf_size + buf->bytes_consumed; 1084 1081 read_subbuf = read_pos / subbuf_size; 1085 1082 padding = buf->padding[read_subbuf]; 1086 1083 padding_start = (read_subbuf + 1) * subbuf_size - padding; ··· 1133 1136 do { 1134 1137 void *from; 1135 1138 1136 - if (!relay_file_read_avail(buf, *ppos)) 1139 + if (!relay_file_read_avail(buf)) 1137 1140 break; 1138 1141 1139 - read_start = relay_file_read_start_pos(*ppos, buf); 1142 + read_start = relay_file_read_start_pos(buf); 1140 1143 avail = relay_file_read_subbuf_avail(read_start, buf); 1141 1144 if (!avail) 1142 1145 break;