linux/fs/ext2
Jan Kara 316cb4ef3e ext2: fix data corruption for racing writes
If two writers allocating blocks to file race with each other (e.g.
because writepages races with ordinary write or two writepages race with
each other), ext2_getblock() can be called on the same inode in parallel.
Before we are going to allocate new blocks, we have to recheck the block
chain we have obtained so far without holding truncate_mutex.  Otherwise
we could overwrite the indirect block pointer set by the other writer
leading to data loss.

The below test program by Ying is able to reproduce the data loss with ext2
on in BRD in a few minutes if the machine is under memory pressure:

long kMemSize  = 50 << 20;
int kPageSize = 4096;

int main(int argc, char **argv) {
	int status;
	int count = 0;
	int i;
	char *fname = "/mnt/test.mmap";
	char *mem;
	unlink(fname);
	int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0600);
	status = ftruncate(fd, kMemSize);
	mem = mmap(0, kMemSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	// Fill the memory with 1s.
	memset(mem, 1, kMemSize);
	sleep(2);
	for (i = 0; i < kMemSize; i++) {
		int byte_good = mem[i] != 0;
		if (!byte_good && ((i % kPageSize) == 0)) {
			//printf("%d ", i / kPageSize);
			count++;
		}
	}
	munmap(mem, kMemSize);
	close(fd);
	unlink(fname);

	if (count > 0) {
		printf("Running %d bad page\n", count);
		return 1;
	}
	return 0;
}

Cc: Ying Han <yinghan@google.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Jan Kara <jack@suse.cz>
Cc: Mingming Cao <cmm@us.ibm.com>
Cc: <linux-ext4@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-04-13 15:04:33 -07:00
..
acl.c New helper - current_umask() 2009-03-31 23:00:26 -04:00
acl.h [PATCH] sanitize ->permission() prototype 2008-07-26 20:53:14 -04:00
balloc.c ext2: Use lowercase names of quota functions 2009-03-26 02:18:36 +01:00
dir.c ext2: also update the inode on disk when dir is IS_DIRSYNC 2009-01-15 16:39:42 -08:00
ext2.h [PATCH] get rid of on-stack dentry in ext2_get_parent() 2008-10-23 05:13:09 -04:00
file.c generic block based fiemap implementation 2008-10-03 17:32:43 -04:00
fsync.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
ialloc.c ext2: Use lowercase names of quota functions 2009-03-26 02:18:36 +01:00
inode.c ext2: fix data corruption for racing writes 2009-04-13 15:04:33 -07:00
ioctl.c ext2: tighten restrictions on inode flags 2009-01-08 08:31:00 -08:00
Kconfig fs/Kconfig: move ext2, ext3, ext4, JBD, JBD2 out 2008-10-20 11:43:59 -07:00
Makefile [PATCH] Make EXT2_DEBUG work again 2006-06-25 10:01:12 -07:00
namei.c nfsd race fixes: ext2 2008-12-31 18:07:43 -05:00
super.c ext2: Zero our b_size in ext2_quota_read() 2009-03-26 02:18:38 +01:00
symlink.c [PATCH] mark struct inode_operations const 1 2007-02-12 09:48:46 -08:00
xattr_security.c ext2: remove double definitions of xattr macros 2008-07-25 10:53:31 -07:00
xattr_trusted.c ext2: remove double definitions of xattr macros 2008-07-25 10:53:31 -07:00
xattr_user.c ext2: remove double definitions of xattr macros 2008-07-25 10:53:31 -07:00
xattr.c ext2: Use lowercase names of quota functions 2009-03-26 02:18:36 +01:00
xattr.h Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
xip.c [PATCH] move block_device_operations to blkdev.h 2008-10-21 07:47:20 -04:00
xip.h xip: support non-struct page backed memory 2008-04-28 08:58:23 -07:00