sys/vfs/hammer: Avoid volume# inconsistency on mount
authorTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Sun, 9 Aug 2015 19:35:41 +0000 (04:35 +0900)
committerTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Mon, 17 Aug 2015 11:04:27 +0000 (20:04 +0900)
commitc302e84437f9ece78d5cdc8ba4ddaa047d58575b
tree2c324c2344ca97bfc5fc62134a9e30b4578ea194
parent721f311056acc1d8297ce0283ec9eca746158b68
sys/vfs/hammer: Avoid volume# inconsistency on mount

hammer_vfs_mount() should check and compare # of volumes
to mount (# of volumes in mount_hammer arg in blkdevs format)
and vol_count field in volume header.

mount_hammer should fail if they don't match even if it's
technically possible to mount at the moment after newfs.

In the following Example1, it's possible to safely mount
/dev/da1 without /dev/da2:/dev/da3 or
/dev/da1:/dev/da2 without /dev/da3 or
/dev/da1:/dev/da3 without /dev/da2 at this point because
both /dev/da2 and /dev/da3 has no data (only layer2 big-block)
right after newfs_hammer, however if filesystem has enough
data that zone2 next_offset has already reached the missing
volume before unmount, there is going to be inconsistency
between blockmap and actual mounted volumes, which results
in kernel panic. mount needs to avoid this by checking #
of volumes as the Example2 shows.

Example 1. - newfs 3 volumes and then mount 2 volumes
  # newfs_hammer -L TEST /dev/da1 /dev/da2 /dev/da3 > /dev/null
  # mount_hammer /dev/da1:/dev/da2:/dev/da3 /HAMMER
  # mount | grep /HAMMER
  TEST on /HAMMER (hammer, local)
  # hammer volume-blkdevs /HAMMER
  /dev/da1:/dev/da2:/dev/da3
  # umount /HAMMER
  # mount_hammer /dev/da1:/dev/da2 /HAMMER
  # mount | grep /HAMMER
  TEST on /HAMMER (hammer, local)
  # hammer volume-blkdevs /HAMMER
  /dev/da1:/dev/da2

Example 2. - with this commit it fails to mount
  # newfs_hammer -L TEST /dev/da1 /dev/da2 /dev/da3 > /dev/null
  # mount_hammer /dev/da1:/dev/da2:/dev/da3 /HAMMER
  # mount | grep /HAMMER
  TEST on /HAMMER (hammer, local)
  # hammer volume-blkdevs /HAMMER
  /dev/da1:/dev/da2:/dev/da3
  # umount /HAMMER
  # mount_hammer /dev/da1:/dev/da2 /HAMMER
  mount_hammer: Unknown error: Invalid argument
  # dmesg | tail -1
  hammer_mount: volume header says 3 volumes, but 2 installed
  # mount_hammer /dev/da1 /HAMMER
  mount_hammer: Unknown error: Invalid argument
  # dmesg | tail -1
  hammer_mount: volume header says 3 volumes, but 1 installed
sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_ondisk.c
sys/vfs/hammer/hammer_vfsops.c