| From f35f06c35560a86e841631f0243b83a984dc11a9 Mon Sep 17 00:00:00 2001 |
| From: Filipe Manana <fdmanana@suse.com> |
| Date: Tue, 26 Mar 2019 10:49:56 +0000 |
| Subject: Btrfs: do not allow trimming when a fs is mounted with the nologreplay option |
| |
| From: Filipe Manana <fdmanana@suse.com> |
| |
| commit f35f06c35560a86e841631f0243b83a984dc11a9 upstream. |
| |
| Whan a filesystem is mounted with the nologreplay mount option, which |
| requires it to be mounted in RO mode as well, we can not allow discard on |
| free space inside block groups, because log trees refer to extents that |
| are not pinned in a block group's free space cache (pinning the extents is |
| precisely the first phase of replaying a log tree). |
| |
| So do not allow the fitrim ioctl to do anything when the filesystem is |
| mounted with the nologreplay option, because later it can be mounted RW |
| without that option, which causes log replay to happen and result in |
| either a failure to replay the log trees (leading to a mount failure), a |
| crash or some silent corruption. |
| |
| Reported-by: Darrick J. Wong <darrick.wong@oracle.com> |
| Fixes: 96da09192cda ("btrfs: Introduce new mount option to disable tree log replay") |
| CC: stable@vger.kernel.org # 4.9+ |
| Reviewed-by: Nikolay Borisov <nborisov@suse.com> |
| Signed-off-by: Filipe Manana <fdmanana@suse.com> |
| Reviewed-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/btrfs/ioctl.c | 10 ++++++++++ |
| 1 file changed, 10 insertions(+) |
| |
| --- a/fs/btrfs/ioctl.c |
| +++ b/fs/btrfs/ioctl.c |
| @@ -501,6 +501,16 @@ static noinline int btrfs_ioctl_fitrim(s |
| if (!capable(CAP_SYS_ADMIN)) |
| return -EPERM; |
| |
| + /* |
| + * If the fs is mounted with nologreplay, which requires it to be |
| + * mounted in RO mode as well, we can not allow discard on free space |
| + * inside block groups, because log trees refer to extents that are not |
| + * pinned in a block group's free space cache (pinning the extents is |
| + * precisely the first phase of replaying a log tree). |
| + */ |
| + if (btrfs_test_opt(fs_info, NOLOGREPLAY)) |
| + return -EROFS; |
| + |
| rcu_read_lock(); |
| list_for_each_entry_rcu(device, &fs_info->fs_devices->devices, |
| dev_list) { |