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