Messages in this thread | | | Date | Sun, 5 Dec 1999 04:19:07 +0100 | From | Petr Vandrovec <> | Subject | Data 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/
| |