lkml.org 
[lkml]   [2000]   [Sep]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: 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/

\
 
 \ /
  Last update: 2005-03-22 12:38    [W:0.373 / U:1.068 seconds]
©2003-2014 Jasper Spaans. Advertise on this site