Revert Btrfs ro snapshot commit that causes filesystem corruption

This commit is contained in:
Josh Boyer 2014-10-15 12:47:23 -04:00
parent e1712de563
commit ec4608962e
2 changed files with 112 additions and 0 deletions

View File

@ -0,0 +1,105 @@
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Wed, 15 Oct 2014 10:09:50 -0400
Subject: [PATCH] Revert "Btrfs: race free update of commit root for ro
snapshots"
This reverts commit 9c3b306e1c9e6be4be09e99a8fe2227d1005effc.
---
fs/btrfs/inode.c | 36 ------------------------------------
fs/btrfs/ioctl.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 36 deletions(-)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index fc9c0439caa3..d23362f4464e 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5261,42 +5261,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
iput(inode);
inode = ERR_PTR(ret);
}
- /*
- * If orphan cleanup did remove any orphans, it means the tree
- * was modified and therefore the commit root is not the same as
- * the current root anymore. This is a problem, because send
- * uses the commit root and therefore can see inode items that
- * don't exist in the current root anymore, and for example make
- * calls to btrfs_iget, which will do tree lookups based on the
- * current root and not on the commit root. Those lookups will
- * fail, returning a -ESTALE error, and making send fail with
- * that error. So make sure a send does not see any orphans we
- * have just removed, and that it will see the same inodes
- * regardless of whether a transaction commit happened before
- * it started (meaning that the commit root will be the same as
- * the current root) or not.
- */
- if (sub_root->node != sub_root->commit_root) {
- u64 sub_flags = btrfs_root_flags(&sub_root->root_item);
-
- if (sub_flags & BTRFS_ROOT_SUBVOL_RDONLY) {
- struct extent_buffer *eb;
-
- /*
- * Assert we can't have races between dentry
- * lookup called through the snapshot creation
- * ioctl and the VFS.
- */
- ASSERT(mutex_is_locked(&dir->i_mutex));
-
- down_write(&root->fs_info->commit_root_sem);
- eb = sub_root->commit_root;
- sub_root->commit_root =
- btrfs_root_node(sub_root);
- up_write(&root->fs_info->commit_root_sem);
- free_extent_buffer(eb);
- }
- }
}
return inode;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 0fe1aa047f15..8d2b76e29d3b 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -713,6 +713,39 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
if (ret)
goto fail;
+ ret = btrfs_orphan_cleanup(pending_snapshot->snap);
+ if (ret)
+ goto fail;
+
+ /*
+ * If orphan cleanup did remove any orphans, it means the tree was
+ * modified and therefore the commit root is not the same as the
+ * current root anymore. This is a problem, because send uses the
+ * commit root and therefore can see inode items that don't exist
+ * in the current root anymore, and for example make calls to
+ * btrfs_iget, which will do tree lookups based on the current root
+ * and not on the commit root. Those lookups will fail, returning a
+ * -ESTALE error, and making send fail with that error. So make sure
+ * a send does not see any orphans we have just removed, and that it
+ * will see the same inodes regardless of whether a transaction
+ * commit happened before it started (meaning that the commit root
+ * will be the same as the current root) or not.
+ */
+ if (readonly && pending_snapshot->snap->node !=
+ pending_snapshot->snap->commit_root) {
+ trans = btrfs_join_transaction(pending_snapshot->snap);
+ if (IS_ERR(trans) && PTR_ERR(trans) != -ENOENT) {
+ ret = PTR_ERR(trans);
+ goto fail;
+ }
+ if (!IS_ERR(trans)) {
+ ret = btrfs_commit_transaction(trans,
+ pending_snapshot->snap);
+ if (ret)
+ goto fail;
+ }
+ }
+
inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
if (IS_ERR(inode)) {
ret = PTR_ERR(inode);
--
1.9.3

View File

@ -609,6 +609,8 @@ Patch26037: HID-usbhid-always-poll-quirk-for-Elan-Touchscreen-00.patch
Patch26038: USB-quirks-device-qualifier-quirk-for-another-Elan-t.patch
Patch26039: HID-usbhid-always-poll-quirk-for-Elan-Touchscreen-01.patch
Patch26040: Revert-Btrfs-race-free-update-of-commit-root-for-ro-.patch
# git clone ssh://git.fedorahosted.org/git/kernel-arm64.git, git diff master...devel
Patch30000: kernel-arm64.patch
@ -1330,6 +1332,8 @@ ApplyPatch HID-usbhid-always-poll-quirk-for-Elan-Touchscreen-00.patch
ApplyPatch USB-quirks-device-qualifier-quirk-for-another-Elan-t.patch
ApplyPatch HID-usbhid-always-poll-quirk-for-Elan-Touchscreen-01.patch
ApplyPatch Revert-Btrfs-race-free-update-of-commit-root-for-ro-.patch
%if 0%{?aarch64patches}
ApplyPatch kernel-arm64.patch
%ifnarch aarch64 # this is stupid, but i want to notice before secondary koji does.
@ -2198,6 +2202,9 @@ fi
# ||----w |
# || ||
%changelog
* Wed Oct 15 2014 Josh Boyer <jwboyer@fedoraproject.org>
- Revert Btrfs ro snapshot commit that causes filesystem corruption
* Wed Oct 15 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.18.0-0.rc0.git9.1
- Linux v3.17-9670-g0429fbc0bdc2