[PATCH 0/2] bd_invalidated shoud be cleared in revalidate_disk

From: MITSUNARI Shigeo
Date: Thu Oct 18 2012 - 23:25:10 EST

rescan_partitions() and invalidate_partitions() in block/partition-generic.c
set bdev->bd_invalidated = 0 after calling check_disk_size_change().
But revalidate_disk() in fs/block_dev.c does not clear it.

If bdev->bd_invalidated = 1 then rescan_partitions() is called when
__blkdev_get() is called.
So if revalidate_disk() is once called, all buffer cache pages will be
cleared whenever the device is opened.

This bug causes the following problem.

mdadm monitor will clear file cache every 1000 seconds
after mdadm resize is executed once.
mdadm monitor only openes the device with O_RDONLY.

We verified the problem occurred at kernel 3.6.2 and mdadm v3.2.5 on
ubuntu 12.04LTS x86_64 and the patch worked well.
The following steps will reproduce the problem.

1. prepair a block device(ex. /dev/sdb).
2. create two partitions.

sudo parted /dev/sdb
mklabel gpt
mkpart primary 0% 50%
mkpart primary 50% 100%

3. create a md device.

sudo mdadm -C /dev/md/hoge -l 1 -n 2 -e 1.2 --assume-clean --auto=md \
--symlink=no /dev/sdb1 /dev/sdb2

4. create file system and mount it

sudo mkfs.ext3 /dev/md/hoge
sudo mkdir /mnt/test
sudo mount /dev/md/hoge /mnt/test

5. try to resize the device

sudo mdadm -G /dev/md/hoge --size=max

6. create a file to fill file cache.

sudo dd if=/dev/urandom of=/mnt/test/data bs=1M count=10
and verity the current status of file by free command.

7. mdadm monitor will open the md device every 1000 seconds
and you will find all file cache on the device are cleared.

The timing can be reduced by the following steps.

a) kill mdadm and restart it with --delay option
/sbin/mdadm --monitor --delay=30 --pid-file /var/run/mdadm/monitor.pid \
--daemonise --scan --syslog

or open the md device directly.

sudo dd if=/dev/md/hoge of=/dev/null bs=4096 count=1

MITSUNARI Shigeo (2):
block: fs: bd_invalidated should be cleared in revalidate_disk
block: fs: move 'bdev->bd_invalidated = 0' into
check_disk_size_change() instead of putting the code every time
after check_disk_size_change().

block/partition-generic.c | 2 --
fs/block_dev.c | 1 +
2 files changed, 1 insertion(+), 2 deletions(-)


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