From: Alexander Shishkin alexander.shishkin@linux.intel.com
mainline inclusion from mainline-v5.3-rc1 commit f505e91ef511a20b2bc3d0eaca41faecdb715027 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I47H3V CVE: NA
--------------------------------
In multi-window mode, the read iterator is supposed to start from the window with the oldest data, which is, chronologically, the next window after the one with the newest data. This, however, fails to take into account the potentially empty windows, so in short trace sessions it's possible to have a lot of zeroes read from the character device first.
Fix this by skipping over the empty windows in initialization of the read iterator.
Signed-off-by: Alexander Shishkin alexander.shishkin@linux.intel.com Reviewed-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Link: https://lore.kernel.org/r/20190627125152.54905-5-alexander.shishkin@linux.in... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Jackie Liu liuyun01@kylinos.cn Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/hwtracing/intel_th/msu.c | 42 +++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 9 deletions(-)
diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index f8e19630f2e69..fc998099dfddd 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -189,17 +189,18 @@ static struct msc_window *msc_next_window(struct msc_window *win) }
/** - * msc_oldest_window() - locate the window with oldest data + * msc_find_window() - find a window matching a given sg_table * @msc: MSC device + * @sgt: SG table of the window + * @nonempty: skip over empty windows * - * This should only be used in multiblock mode. Caller should hold the - * msc::user_count reference. - * - * Return: the oldest window with valid data + * Return: MSC window structure pointer or NULL if the window + * could not be found. */ -static struct msc_window *msc_oldest_window(struct msc *msc) +static struct msc_window * +msc_find_window(struct msc *msc, struct sg_table *sgt, bool nonempty) { - struct msc_window *win, *next = msc_next_window(msc->cur_win); + struct msc_window *win; unsigned int found = 0;
if (list_empty(&msc->win_list)) @@ -211,17 +212,40 @@ static struct msc_window *msc_oldest_window(struct msc *msc) * something like 2, in which case we're good */ list_for_each_entry(win, &msc->win_list, entry) { - if (win == next) + if (win->sgt == sgt) found++;
/* skip the empty ones */ - if (msc_block_is_empty(msc_win_block(win, 0))) + if (nonempty && msc_block_is_empty(msc_win_block(win, 0))) continue;
if (found) return win; }
+ return NULL; +} + +/** + * msc_oldest_window() - locate the window with oldest data + * @msc: MSC device + * + * This should only be used in multiblock mode. Caller should hold the + * msc::user_count reference. + * + * Return: the oldest window with valid data + */ +static struct msc_window *msc_oldest_window(struct msc *msc) +{ + struct msc_window *win; + + if (list_empty(&msc->win_list)) + return NULL; + + win = msc_find_window(msc, msc_next_window(msc->cur_win)->sgt, true); + if (win) + return win; + return list_first_entry(&msc->win_list, struct msc_window, entry); }