g***@linuxfoundation.org
2014-10-19 23:12:02 UTC
This is a note to let you know that I've just added the patch titled
Btrfs: fix race in WAIT_SYNC ioctl
to the 3.16-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
btrfs-fix-race-in-wait_sync-ioctl.patch
and it can be found in the queue-3.16 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
Date: Fri, 26 Sep 2014 08:30:06 -0700
Subject: Btrfs: fix race in WAIT_SYNC ioctl
From: Sage Weil <***@redhat.com>
commit 42383020beb1cfb05f5d330cc311931bc4917a97 upstream.
We check whether transid is already committed via last_trans_committed and
then search through trans_list for pending transactions. If
last_trans_committed is updated by btrfs_commit_transaction after we check
it (there is no locking), we will fail to find the committed transaction
and return EINVAL to the caller. This has been observed occasionally by
ceph-osd (which uses this ioctl heavily).
Fix by rechecking whether the provided transid <= last_trans_committed
after the search fails, and if so return 0.
Signed-off-by: Sage Weil <***@redhat.com>
Signed-off-by: Chris Mason <***@fb.com>
Signed-off-by: Greg Kroah-Hartman <***@linuxfoundation.org>
---
fs/btrfs/transaction.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -609,7 +609,6 @@ int btrfs_wait_for_commit(struct btrfs_r
if (transid <= root->fs_info->last_trans_committed)
goto out;
- ret = -EINVAL;
/* find specified transaction */
spin_lock(&root->fs_info->trans_lock);
list_for_each_entry(t, &root->fs_info->trans_list, list) {
@@ -625,9 +624,16 @@ int btrfs_wait_for_commit(struct btrfs_r
}
}
spin_unlock(&root->fs_info->trans_lock);
- /* The specified transaction doesn't exist */
- if (!cur_trans)
+
+ /*
+ * The specified transaction doesn't exist, or we
+ * raced with btrfs_commit_transaction
+ */
+ if (!cur_trans) {
+ if (transid > root->fs_info->last_trans_committed)
+ ret = -EINVAL;
goto out;
+ }
} else {
/* find newest transaction that is committing | committed */
spin_lock(&root->fs_info->trans_lock);
Patches currently in stable-queue which might be from ***@redhat.com are
queue-3.16/btrfs-fix-race-in-wait_sync-ioctl.patch
Btrfs: fix race in WAIT_SYNC ioctl
to the 3.16-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
btrfs-fix-race-in-wait_sync-ioctl.patch
and it can be found in the queue-3.16 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
From 42383020beb1cfb05f5d330cc311931bc4917a97 Mon Sep 17 00:00:00 2001
From: Sage Weil <***@redhat.com>Date: Fri, 26 Sep 2014 08:30:06 -0700
Subject: Btrfs: fix race in WAIT_SYNC ioctl
From: Sage Weil <***@redhat.com>
commit 42383020beb1cfb05f5d330cc311931bc4917a97 upstream.
We check whether transid is already committed via last_trans_committed and
then search through trans_list for pending transactions. If
last_trans_committed is updated by btrfs_commit_transaction after we check
it (there is no locking), we will fail to find the committed transaction
and return EINVAL to the caller. This has been observed occasionally by
ceph-osd (which uses this ioctl heavily).
Fix by rechecking whether the provided transid <= last_trans_committed
after the search fails, and if so return 0.
Signed-off-by: Sage Weil <***@redhat.com>
Signed-off-by: Chris Mason <***@fb.com>
Signed-off-by: Greg Kroah-Hartman <***@linuxfoundation.org>
---
fs/btrfs/transaction.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -609,7 +609,6 @@ int btrfs_wait_for_commit(struct btrfs_r
if (transid <= root->fs_info->last_trans_committed)
goto out;
- ret = -EINVAL;
/* find specified transaction */
spin_lock(&root->fs_info->trans_lock);
list_for_each_entry(t, &root->fs_info->trans_list, list) {
@@ -625,9 +624,16 @@ int btrfs_wait_for_commit(struct btrfs_r
}
}
spin_unlock(&root->fs_info->trans_lock);
- /* The specified transaction doesn't exist */
- if (!cur_trans)
+
+ /*
+ * The specified transaction doesn't exist, or we
+ * raced with btrfs_commit_transaction
+ */
+ if (!cur_trans) {
+ if (transid > root->fs_info->last_trans_committed)
+ ret = -EINVAL;
goto out;
+ }
} else {
/* find newest transaction that is committing | committed */
spin_lock(&root->fs_info->trans_lock);
Patches currently in stable-queue which might be from ***@redhat.com are
queue-3.16/btrfs-fix-race-in-wait_sync-ioctl.patch