On Mon, Feb 6, 2023 at 9:34 AM George Kennedy <george.kennedy@xxxxxxxxxx> wrote: > > > - ret = -ENXIO; > vc = vcs_vc(inode, &viewed); > - if (!vc) > + if (!vc) { > + if (read) > + break; > + ret = -ENXIO; > goto unlock_out; > + } That works, but the whole "if (read)" thing is already done after the loop, so instead of essentially duplicating that logic, I really think the patch should be just a plain vc = vcs_vc(inode, &viewed); if (!vc) - goto unlock_out; + break; and nothing else. And yes, the pre-existing vcs_size() error handling has that same ugly pattern. It might be worth cleaning up too, although right now that size = vcs_size(vc, attr, uni_mode); if (size < 0) { if (read) break; pattern means that if we 'break' there, 'read' is non-zero, so 'ret' doesn't matter. Which is also ugly, but works. I *think* it could all be rewritten to just use 'break' everywhere in the loop, and make 'ret' handling be saner. Something like the attached patch, but while I tried to think about it, I didn't spend a lot of effort on it, and I certainly didn't test it. So I'm sending this out as a "Hmm. This _looks_ better to me, but whatever" patch. Linus
drivers/tty/vt/vc_screen.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index f566eb1839dc..c599b452969f 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -406,19 +406,17 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) ret = -ENXIO; vc = vcs_vc(inode, &viewed); if (!vc) - goto unlock_out; + break; /* Check whether we are above size each round, * as copy_to_user at the end of this loop * could sleep. */ - size = vcs_size(vc, attr, uni_mode); - if (size < 0) { - if (read) - break; - ret = size; - goto unlock_out; - } + ret = vcs_size(vc, attr, uni_mode); + if (ret < 0) + break; + size = ret; + ret = 0; if (pos >= size) break; if (count > size - pos)