diff options
Diffstat (limited to 'Btrfs-fix-fitrim-discarding-device-area-reserved-for.patch')
-rw-r--r-- | Btrfs-fix-fitrim-discarding-device-area-reserved-for.patch | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/Btrfs-fix-fitrim-discarding-device-area-reserved-for.patch b/Btrfs-fix-fitrim-discarding-device-area-reserved-for.patch new file mode 100644 index 000000000..63f66fb1b --- /dev/null +++ b/Btrfs-fix-fitrim-discarding-device-area-reserved-for.patch @@ -0,0 +1,119 @@ +From 259072b7a1c20f8612dcaa8e0e027004aa98f864 Mon Sep 17 00:00:00 2001 +From: Filipe Manana <fdmanana@suse.com> +Date: Wed, 6 Jan 2016 22:42:35 +0000 +Subject: [PATCH 2/2] Btrfs: fix fitrim discarding device area reserved for + boot loader's use + +As of the 4.3 kernel release, the fitrim ioctl can now discard any region +of a disk that is not allocated to any chunk/block group, including the +first megabyte which is used for our primary superblock and by the boot +loader (grub for example). + +Fix this by not allowing to trim/discard any region in the device starting +with an offset not greater than min(alloc_start_mount_option, 1Mb), just +as it was not possible before 4.3. + +A reproducer test case for xfstests follows. + + seq=`basename $0` + seqres=$RESULT_DIR/$seq + echo "QA output created by $seq" + tmp=/tmp/$$ + status=1 # failure is the default! + trap "_cleanup; exit \$status" 0 1 2 3 15 + + _cleanup() + { + cd / + rm -f $tmp.* + } + + # get standard environment, filters and checks + . ./common/rc + . ./common/filter + + # real QA test starts here + _need_to_be_root + _supported_fs btrfs + _supported_os Linux + _require_scratch + + rm -f $seqres.full + + _scratch_mkfs >>$seqres.full 2>&1 + + # Write to the [0, 64Kb[ and [68Kb, 1Mb[ ranges of the device. These ranges are + # reserved for a boot loader to use (GRUB for example) and btrfs should never + # use them - neither for allocating metadata/data nor should trim/discard them. + # The range [64Kb, 68Kb[ is used for the primary superblock of the filesystem. + $XFS_IO_PROG -c "pwrite -S 0xfd 0 64K" $SCRATCH_DEV | _filter_xfs_io + $XFS_IO_PROG -c "pwrite -S 0xfd 68K 956K" $SCRATCH_DEV | _filter_xfs_io + + # Now mount the filesystem and perform a fitrim against it. + _scratch_mount + _require_batched_discard $SCRATCH_MNT + $FSTRIM_PROG $SCRATCH_MNT + + # Now unmount the filesystem and verify the content of the ranges was not + # modified (no trim/discard happened on them). + _scratch_unmount + echo "Content of the ranges [0, 64Kb] and [68Kb, 1Mb[ after fitrim:" + od -t x1 -N $((64 * 1024)) $SCRATCH_DEV + od -t x1 -j $((68 * 1024)) -N $((956 * 1024)) $SCRATCH_DEV + + status=0 + exit + +Reported-by: Vincent Petry <PVince81@yahoo.fr> +Reported-by: Andrei Borzenkov <arvidjaar@gmail.com> +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=109341 +Fixes: 499f377f49f0 (btrfs: iterate over unused chunk space in FITRIM) +Cc: stable@vger.kernel.org # 4.3+ +Signed-off-by: Filipe Manana <fdmanana@suse.com> +--- + fs/btrfs/volumes.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index b816b3a2e118..96f8c827d563 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -1208,6 +1208,15 @@ int find_free_dev_extent_start(struct btrfs_transaction *transaction, + int ret; + int slot; + struct extent_buffer *l; ++ u64 min_search_start; ++ ++ /* ++ * We don't want to overwrite the superblock on the drive nor any area ++ * used by the boot loader (grub for example), so we make sure to start ++ * at an offset of at least 1MB. ++ */ ++ min_search_start = max(root->fs_info->alloc_start, 1024ull * 1024); ++ search_start = max(search_start, min_search_start); + + path = btrfs_alloc_path(); + if (!path) +@@ -1348,18 +1357,9 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans, + struct btrfs_device *device, u64 num_bytes, + u64 *start, u64 *len) + { +- struct btrfs_root *root = device->dev_root; +- u64 search_start; +- + /* FIXME use last free of some kind */ +- +- /* +- * we don't want to overwrite the superblock on the drive, +- * so we make sure to start at an offset of at least 1MB +- */ +- search_start = max(root->fs_info->alloc_start, 1024ull * 1024); + return find_free_dev_extent_start(trans->transaction, device, +- num_bytes, search_start, start, len); ++ num_bytes, 0, start, len); + } + + static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, +-- +2.5.0 + |