All of lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@ZenIV.linux.org.uk>
To: "Alan J. Wylie" <alan@wylie.me.uk>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Thorsten Leemhuis <regressions@leemhuis.info>,
	linux-kernel <linux-kernel@vger.kernel.org>
Subject: Re: 4.9.0 regression in pipe-backed iov_iter with systemd-nspawn
Date: Fri, 13 Jan 2017 11:18:42 +0000	[thread overview]
Message-ID: <20170113111842.GL1555@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20170113102019.GK1555@ZenIV.linux.org.uk>

On Fri, Jan 13, 2017 at 10:20:19AM +0000, Al Viro wrote:

> OK, so it is iov_iter_advance() failing to free the shit allocated, either
> due to some breakage in pipe_advance() or buggered 'copied'...  Let's
> see which one; could you apply the following and run your reproducer?  The
> only difference from the previous is that it collects and prints a bit more,
> so it should be just as reproducible...

Actually, I think I understand what's going on.  It's
        if (pipe->nrbufs) {
                int unused = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
                /* [curbuf,unused) is in use.  Free [idx,unused) */
                while (idx != unused) {
                        pipe_buf_release(pipe, &pipe->bufs[idx]);
                        idx = next_idx(idx, pipe);
                        pipe->nrbufs--;
                }
        }
in case when pipe->nrbufs == pipe->buffers and idx == pipe->curbuf.  IOW,
we have a full pipe and want to empty it entirely; the fun question is,
of course, telling that case from having nothing to free with the same
full pipe...

OK, so we have either
	* off != 0 => something's being left in the pipe, i->idx points
to the last in-use buffer after that, idx points to the first buffer unused
after that.  In that case the current logics is correct.
	* off == 0 => we are emptying the damn thing.  i->idx and idx point
to the first buffer unused after that (== pipe->curbuf + pipe->nrbufs at the
time we'd set the iov_iter up).  The current logics is correct unless
pipe->nrbufs was originally 0 and now has become pipe->buffers.  IOW,
we screw up when off == 0, idx == unused, pipe->nrbufs == pipe->buffers...

	OK, we really ought to make sure that iov_iter_pipe() is never
done on a full pipe.  AFAICS, we do, and if so the following should
suffice.  WARNING: it's completely untested and it's a result of debugging
a fencepost bug in handling of cyclic buffers done at 6 in the morning,
on _way_ too long uptime.  Treat as very dangerous; it's not entirely
impossible that I hadn't fucked up, but don't consider it anything other
than "let's try and see if it immediately explodes" until I've got
a chance to reread it after getting some sleep.

diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 25f572303801..7bc0b99d3c83 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -759,11 +759,12 @@ static void pipe_advance(struct iov_iter *i, size_t size)
 		idx = next_idx(idx, pipe);
 	if (pipe->nrbufs) {
 		int unused = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
-		/* [curbuf,unused) is in use.  Free [idx,unused) */
-		while (idx != unused) {
-			pipe_buf_release(pipe, &pipe->bufs[idx]);
-			idx = next_idx(idx, pipe);
-			pipe->nrbufs--;
+		if (idx != unused || unlikely(idx == pipe->curbuf && !off)) {
+			do {
+				pipe_buf_release(pipe, &pipe->bufs[idx]);
+				idx = next_idx(idx, pipe);
+				pipe->nrbufs--;
+			} while (idx != unused);
 		}
 	}
 	i->count -= orig_sz;
@@ -826,6 +827,7 @@ void iov_iter_pipe(struct iov_iter *i, int direction,
 			size_t count)
 {
 	BUG_ON(direction != ITER_PIPE);
+	WARN_ON(pipe->nrbufs == pipe->buffers);
 	i->type = direction;
 	i->pipe = pipe;
 	i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);

  parent reply	other threads:[~2017-01-13 11:18 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-12 20:26 4.9.0 regression in pipe-backed iov_iter with systemd-nspawn Alan J. Wylie
2017-01-12 20:31 ` Al Viro
2017-01-12 20:38   ` Alan J. Wylie
2017-01-12 22:26 ` Linus Torvalds
2017-01-12 22:37   ` Al Viro
2017-01-12 22:46     ` Al Viro
2017-01-12 23:02       ` Linus Torvalds
2017-01-12 23:14         ` Al Viro
2017-01-12 23:14         ` Linus Torvalds
2017-01-12 23:27           ` Al Viro
2017-01-12 22:46   ` Alan J. Wylie
2017-01-12 22:58     ` Al Viro
2017-01-12 23:28     ` Linus Torvalds
2017-01-13  4:00       ` Al Viro
2017-01-13  7:38         ` Alan J. Wylie
2017-01-13  7:23       ` Alan J. Wylie
2017-01-13  9:33         ` Al Viro
2017-01-13  9:54           ` Alan J. Wylie
2017-01-13 10:20             ` Al Viro
2017-01-13 10:32               ` Alan J. Wylie
2017-01-13 11:25                 ` Al Viro
2017-01-13 11:18               ` Al Viro [this message]
2017-01-13 19:33                 ` Linus Torvalds
2017-01-13 20:08                   ` Al Viro
2017-01-13 20:11                     ` Al Viro
2017-01-13 20:32                       ` Linus Torvalds
2017-01-13 20:47                         ` Al Viro
2017-01-13 21:55                           ` Al Viro
2017-01-13 21:59                             ` Al Viro
2017-01-13 22:13                               ` Al Viro
2017-01-13 22:50                                 ` Al Viro
2017-01-14  0:59                                   ` Linus Torvalds
2017-01-14  1:24                                     ` Al Viro
2017-01-14  1:43                                       ` Al Viro
2017-01-14  1:46                                       ` Linus Torvalds
2017-01-14  1:57                                         ` Al Viro
2017-01-15  0:53                                           ` Al Viro
2017-01-14 13:16                                   ` Alan J. Wylie
2017-01-14 16:29                                     ` Alan J. Wylie
2017-01-14 17:57                                       ` Linus Torvalds
2017-01-13 20:08                   ` Linus Torvalds
2017-01-13 20:16                     ` Al Viro

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170113111842.GL1555@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=alan@wylie.me.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=regressions@leemhuis.info \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.