Re: 2.6.24-sha1: RIP [<ffffffff802596c8>] iov_iter_advance+0x38/0x70
From: Nick Piggin
Date: Mon Feb 25 2008 - 22:47:21 EST
On Wednesday 20 February 2008 09:01, Alexey Dobriyan wrote:
> On Tue, Feb 19, 2008 at 11:47:11PM +0300, wrote:
> > > Are you reproducing it simply by running the
> > > ftest03 binary directly from the shell? How many times between oopses?
> > > It is multi-process but no threads, so races should be minimal down
> > > this path -- can you get an strace of the failing process?
>
> Speaking of multi-proceseness, changing MAXCHILD to 1, nchild to 1,
> AFAICS, generates one child which oopses the very same way (in parallel
> with generic LTP) But, lowering MAXIOVCNT to 8 generates no oops.
Thanks, I was able to reproduce quite easily with these settings.
I think I have the correct patch now (at least it isn't triggerable
any more here).
Thanks,
Nick
diff --git a/mm/filemap.c b/mm/filemap.c
index 5c74b68..2650073 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1750,14 +1750,18 @@ static void __iov_iter_advance_iov(struct iov_iter *i, size_t bytes)
} else {
const struct iovec *iov = i->iov;
size_t base = i->iov_offset;
+ size_t copied = 0;
/*
* The !iov->iov_len check ensures we skip over unlikely
- * zero-length segments.
+ * zero-length segments (without overruning the iovec).
*/
- while (bytes || !iov->iov_len) {
- int copy = min(bytes, iov->iov_len - base);
+ while (copied < bytes ||
+ unlikely(!iov->iov_len && copied < i->count)) {
+ int copy;
+ copy = min(bytes, iov->iov_len - base);
+ copied += copy;
bytes -= copy;
base += copy;
if (iov->iov_len == base) {