Messages in this thread Patch in this message | | | Date | Tue, 5 Sep 2000 21:31:17 -0400 (EDT) | From | Alexander Viro <> | Subject | Re: Still ext2-corruption in test8-pre5 (incl. OOPS) |
| |
On Tue, 5 Sep 2000, Linus Torvalds wrote:
> > > On Tue, 5 Sep 2000, Alexander Viro wrote: > > > > WTF? <thinks> Erm... Linus, I suspect that we are losing the thing on the > > very simple effect: readpage() gets buffer_heads, all right, but then > > we lose the lock. That's your window for losing the buffer_head ring of > > that page. > > Note that it's not even a small window: we get an up-to-date page, but > readpage() can have happened hours, days, years before. The buffer-head > ring _has_ been there at some earlier time, but there's nothing that > guarantees that it still is there. > > Fixing this is not hard, happily. I'll do it. The only issue is whether to > just copy one of the existing functions and make changes, or try to share > code and have helper functions. The loop over the page doing the > get_block() is certainly something that all of the functions for > reading/writing need to do, and I suspect that I really should split > things up a bit and share more code than we do now. > > If you WANT to do it, holler. I'm not glutton for punishment, but it > doesn't look that bad.
Me neither, but IMO I have a cop-out:
--- buffer.c Tue Sep 5 21:23:41 2000 +++ buffer.c.new Tue Sep 5 21:28:53 2000 @@ -1724,12 +1724,24 @@ return 0; } +/* + * If it would be '74 that would go into libc... + */ +int mem_is_zero(char *p, unsigned len) +{ + while (len--) + if (*p++) + return 0; + return 1; +} + int block_zero_page(struct address_space *mapping, loff_t from, unsigned length) { unsigned long index = from >> PAGE_CACHE_SHIFT; unsigned offset = from & (PAGE_CACHE_SIZE-1); struct inode *inode = (struct inode *)mapping->host; struct page *page; + char *kaddr; int err; if (!length) @@ -1745,9 +1757,18 @@ if (!Page_Uptodate(page)) goto unlock; - memset((char *) kmap(page) + offset, 0, length); + kaddr = (char*)kmap(page); + err = 0; + if (mem_is_zero(kaddr+offset, length)) + goto unmap; + err = mapping->a_ops->prepare_write(NULL, page, offset, offset+length); + if (err) + goto unmap; + memset(kaddr+offset, 0, length); flush_dcache_page(page); __block_commit_write(inode, page, offset, offset+length); + kunmap(page); +unmap: kunmap(page); err = 0; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/
| |