lkml.org 
[lkml]   [1999]   [Dec]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectData corruption with 2.3.30-pre5 (probably all 30-preX)
Hi,
for some time I was seeing that I'm getting parts of files
overwritten by zeroes - last line overwritten with zeroes
in /etc/mtab, damaged just downloaded *.deb file and so on.
After some searching I found following code, which executes
on write() request.
It looks to me like that if
block_end <= zerofrom || block_start >= zeroto
no-one marks buffer dirty... And because of default value
of 'zeroto' is zero, it is sometime trigerred.
Because of this is important filesystem/buffer code and
I'm not too familiar with it, there is no patch attached.
But quick fix looks like moving 'else' branch (marked
with /******/ by me in code below) into both code paths,
not only into full-write path.
I'll do it and I'll see, it cannot be worse, I think.
If I run testprogram, 'cat asd' then prints 'asdfghjk'.
If I do 'cat /600MBfile >/dev/null' after that, 'od -c'
says
0000000 a s d f \0 \0 \0 \0
0000010
and it is wrong, isn't it?
[I'm using IDE, if it matters, but I do not think...]
Thanks for your time,
Petr Vandrovec
vandrove@vc.cvut.cz

int block_write_range(struct dentry *dentry, struct page *page,
unsigned zerofrom, unsigned from, unsigned to,
const char * buf)
{
struct inode *inode = dentry->d_inode;
unsigned zeroto = 0, block_start, block_end;
unsigned long block;
[snip]
if (buffer_new(bh)) {
zeroto = block_end;
if (block_start < zerofrom)
zerofrom = block_start;
continue;
}
[snip]
while(wait_bh > wait) {
wait_on_buffer(*--wait_bh);
err = -EIO;
if (!buffer_uptodate(*wait_bh))
goto out;
}
[snip]
for(bh = head, block_start = 0;
bh != head || !block_start;
block_start=block_end, bh = bh->b_this_page) {
block_end = block_start + blocksize;
if (block_end <= zerofrom || block_start >= zeroto) {
if (!buffer_uptodate(bh))
partial = 1;
} else { /******/
set_bit(BH_Uptodate, &bh->b_state);
if (!test_and_set_bit(BH_Dirty, &bh->b_state)) {
__mark_dirty(bh, 0);
need_balance_dirty = 1;
}
}
}
[snip]
if (!partial)
SetPageUptodate(page);
kunmap(page);
return 0;


/* test program */
#include <unistd.h>
#include <fcntl.h>

int main(void) {
int fd = open("asd", O_RDWR|O_TRUNC|O_CREAT, 0600);

write(fd, "asdf", 4);
sync();
write(fd, "ghjk", 4);
close(fd);
return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.044 / U:0.068 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site