android_kernel_samsung_msm8976/fs/nilfs2
Andreas Rohner a0778f7069 nilfs2: fix data loss with mmap()
commit 56d7acc792c0d98f38f22058671ee715ff197023 upstream.

This bug leads to reproducible silent data loss, despite the use of
msync(), sync() and a clean unmount of the file system.  It is easily
reproducible with the following script:

  ----------------[BEGIN SCRIPT]--------------------
  mkfs.nilfs2 -f /dev/sdb
  mount /dev/sdb /mnt

  dd if=/dev/zero bs=1M count=30 of=/mnt/testfile

  umount /mnt
  mount /dev/sdb /mnt
  CHECKSUM_BEFORE="$(md5sum /mnt/testfile)"

  /root/mmaptest/mmaptest /mnt/testfile 30 10 5

  sync
  CHECKSUM_AFTER="$(md5sum /mnt/testfile)"
  umount /mnt
  mount /dev/sdb /mnt
  CHECKSUM_AFTER_REMOUNT="$(md5sum /mnt/testfile)"
  umount /mnt

  echo "BEFORE MMAP:\t$CHECKSUM_BEFORE"
  echo "AFTER MMAP:\t$CHECKSUM_AFTER"
  echo "AFTER REMOUNT:\t$CHECKSUM_AFTER_REMOUNT"
  ----------------[END SCRIPT]--------------------

The mmaptest tool looks something like this (very simplified, with
error checking removed):

  ----------------[BEGIN mmaptest]--------------------
  data = mmap(NULL, file_size - file_offset, PROT_READ | PROT_WRITE,
              MAP_SHARED, fd, file_offset);

  for (i = 0; i < write_count; ++i) {
        memcpy(data + i * 4096, buf, sizeof(buf));
        msync(data, file_size - file_offset, MS_SYNC))
  }
  ----------------[END mmaptest]--------------------

The output of the script looks something like this:

  BEFORE MMAP:    281ed1d5ae50e8419f9b978aab16de83  /mnt/testfile
  AFTER MMAP:     6604a1c31f10780331a6850371b3a313  /mnt/testfile
  AFTER REMOUNT:  281ed1d5ae50e8419f9b978aab16de83  /mnt/testfile

So it is clear, that the changes done using mmap() do not survive a
remount.  This can be reproduced a 100% of the time.  The problem was
introduced in commit 136e8770cd ("nilfs2: fix issue of
nilfs_set_page_dirty() for page at EOF boundary").

If the page was read with mpage_readpage() or mpage_readpages() for
example, then it has no buffers attached to it.  In that case
page_has_buffers(page) in nilfs_set_page_dirty() will be false.
Therefore nilfs_set_file_dirty() is never called and the pages are never
collected and never written to disk.

This patch fixes the problem by also calling nilfs_set_file_dirty() if the
page has no buffers attached to it.

[akpm@linux-foundation.org: s/PAGE_SHIFT/PAGE_CACHE_SHIFT/]
Signed-off-by: Andreas Rohner <andreas.rohner@gmx.net>
Tested-by: Andreas Rohner <andreas.rohner@gmx.net>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-10-05 14:54:14 -07:00
..
alloc.c nilfs2: use mark_buffer_dirty to mark btnode or meta data dirty 2011-05-10 22:21:57 +09:00
alloc.h nilfs2: add omitted comments for different structures in driver implementation 2012-07-30 17:25:19 -07:00
bmap.c nilfs2: get rid of NILFS_I_NILFS 2011-05-10 22:21:56 +09:00
bmap.h nilfs2: add omitted comments for different structures in driver implementation 2012-07-30 17:25:19 -07:00
btnode.c nilfs2: use mark_buffer_dirty to mark btnode or meta data dirty 2011-05-10 22:21:57 +09:00
btnode.h nilfs2: add omitted comments for different structures in driver implementation 2012-07-30 17:25:19 -07:00
btree.c nilfs2: fix missing block address termination in btree node shrinking 2011-06-11 15:51:15 +09:00
btree.h nilfs2: get rid of nilfs_bmap_union 2010-07-23 10:02:14 +09:00
cpfile.c nilfs2: fix timing issue between rmcp and chcp ioctls 2012-07-30 17:25:19 -07:00
cpfile.h nilfs2: use iget for all metadata files 2010-10-23 09:24:38 +09:00
dat.c nilfs2: add omitted comments for different structures in driver implementation 2012-07-30 17:25:19 -07:00
dat.h nilfs2: use iget for all metadata files 2010-10-23 09:24:38 +09:00
dir.c new helper: file_inode(file) 2013-02-22 23:31:31 -05:00
direct.c nilfs2: record used amount of each checkpoint in checkpoint list 2011-03-08 14:58:31 +09:00
direct.h nilfs2: get rid of nilfs_bmap_union 2010-07-23 10:02:14 +09:00
export.h nilfs2: add omitted comments for different structures in driver implementation 2012-07-30 17:25:19 -07:00
file.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-02-26 20:16:07 -08:00
gcinode.c nilfs2: ensure proper cache clearing for gc-inodes 2012-06-20 14:39:35 -07:00
ifile.c nilfs2: add omitted comments for different structures in driver implementation 2012-07-30 17:25:19 -07:00
ifile.h nilfs2: use iget for all metadata files 2010-10-23 09:24:38 +09:00
inode.c nilfs2: fix data loss with mmap() 2014-10-05 14:54:14 -07:00
ioctl.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-02-26 20:16:07 -08:00
Kconfig fs/nilfs2: remove depends on CONFIG_EXPERIMENTAL 2013-01-11 11:39:04 -08:00
Makefile nilfs2: get rid of GCDAT inode 2010-10-23 09:24:38 +09:00
mdt.c nilfs2: fix issue with flush kernel thread after remount in RO mode because of driver's internal error or metadata corruption 2013-04-30 17:04:04 -07:00
mdt.h nilfs2: add omitted comments for different structures in driver implementation 2012-07-30 17:25:19 -07:00
namei.c fs: encode_fh: return FILEID_INVALID if invalid fid_type 2013-02-26 02:46:10 -05:00
nilfs.h nilfs2: drop vmtruncate 2012-12-20 18:40:54 -05:00
page.c nilfs2: fix issue with race condition of competition between segments for dirty blocks 2013-10-13 16:08:32 -07:00
page.h nilfs2: fix issue with flush kernel thread after remount in RO mode because of driver's internal error or metadata corruption 2013-04-30 17:04:04 -07:00
recovery.c nilfs2: drop vmtruncate 2012-12-20 18:40:54 -05:00
segbuf.c nilfs2: fix issue with counting number of bio requests for BIO_EOPNOTSUPP error detection 2013-08-29 09:47:37 -07:00
segbuf.h nilfs2: get rid of macros for segment summary information 2010-07-23 10:02:09 +09:00
segment.c nilfs2: fix segctor bug that causes file system corruption 2014-01-25 08:27:12 -08:00
segment.h nilfs2: get rid of private page allocator 2011-05-10 22:21:44 +09:00
sufile.c nilfs2: add omitted comments for different structures in driver implementation 2012-07-30 17:25:19 -07:00
sufile.h nilfs2: get rid of NILFS_I_NILFS 2011-05-10 22:21:56 +09:00
super.c fs: Limit sys_mount to only request filesystem modules. 2013-03-03 19:36:31 -08:00
the_nilfs.c nilfs2: fix deadlock issue between chcp and thaw ioctls 2012-07-30 17:25:19 -07:00
the_nilfs.h nilfs2: nuke write_super from comments 2012-08-04 12:15:38 +04:00