From 1ebc92a6d9587f2b46a99e6104bcb9d9cdf33b37 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Oct 2014 07:11:58 +0800 Subject: [PATCH] 3.16-stable patches added patches: btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch btrfs-cleanup-error-handling-in-build_backref_tree.patch btrfs-don-t-do-async-reclaim-during-log-replay.patch btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch btrfs-fix-race-in-wait_sync-ioctl.patch btrfs-fix-up-bounds-checking-in-lseek.patch btrfs-try-not-to-enospc-on-log-replay.patch btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch --- ...perty-remove-in-btrfs_ioctl_setflags.patch | 53 +++++ ...error-handling-in-build_backref_tree.patch | 215 ++++++++++++++++++ ...t-do-async-reclaim-during-log-replay.patch | 39 ++++ ...dlock-in-btrfs_dev_replace_finishing.patch | 67 ++++++ ...ee-issue-with-multiple-shared-blocks.patch | 63 +++++ .../btrfs-fix-race-in-wait_sync-ioctl.patch | 56 +++++ ...trfs-fix-up-bounds-checking-in-lseek.patch | 88 +++++++ ...trfs-try-not-to-enospc-on-log-replay.patch | 40 ++++ ...ransaction-thread-from-sync_fs-ioctl.patch | 39 ++++ queue-3.16/series | 8 + 10 files changed, 668 insertions(+) create mode 100644 queue-3.16/btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch create mode 100644 queue-3.16/btrfs-cleanup-error-handling-in-build_backref_tree.patch create mode 100644 queue-3.16/btrfs-don-t-do-async-reclaim-during-log-replay.patch create mode 100644 queue-3.16/btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch create mode 100644 queue-3.16/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch create mode 100644 queue-3.16/btrfs-fix-race-in-wait_sync-ioctl.patch create mode 100644 queue-3.16/btrfs-fix-up-bounds-checking-in-lseek.patch create mode 100644 queue-3.16/btrfs-try-not-to-enospc-on-log-replay.patch create mode 100644 queue-3.16/btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch diff --git a/queue-3.16/btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch b/queue-3.16/btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch new file mode 100644 index 00000000000..bad832e5950 --- /dev/null +++ b/queue-3.16/btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch @@ -0,0 +1,53 @@ +From 78a017a2c92df9b571db0a55a016280f9019c65e Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Thu, 11 Sep 2014 11:44:49 +0100 +Subject: Btrfs: add missing compression property remove in btrfs_ioctl_setflags + +From: Filipe Manana + +commit 78a017a2c92df9b571db0a55a016280f9019c65e upstream. + +The behaviour of a 'chattr -c' consists of getting the current flags, +clearing the FS_COMPR_FL bit and then sending the result to the set +flags ioctl - this means the bit FS_NOCOMP_FL isn't set in the flags +passed to the ioctl. This results in the compression property not being +cleared from the inode - it was cleared only if the bit FS_NOCOMP_FL +was set in the received flags. + +Reproducer: + + $ mkfs.btrfs -f /dev/sdd + $ mount /dev/sdd /mnt && cd /mnt + $ mkdir a + $ chattr +c a + $ touch a/file + $ lsattr a/file + --------c------- a/file + $ chattr -c a + $ touch a/file2 + $ lsattr a/file2 + --------c------- a/file2 + $ lsattr -d a + ---------------- a + +Reported-by: Andreas Schneider +Signed-off-by: Filipe Manana +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/ioctl.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -332,6 +332,9 @@ static int btrfs_ioctl_setflags(struct f + goto out_drop; + + } else { ++ ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0); ++ if (ret && ret != -ENODATA) ++ goto out_drop; + ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS); + } + diff --git a/queue-3.16/btrfs-cleanup-error-handling-in-build_backref_tree.patch b/queue-3.16/btrfs-cleanup-error-handling-in-build_backref_tree.patch new file mode 100644 index 00000000000..66eb50003f8 --- /dev/null +++ b/queue-3.16/btrfs-cleanup-error-handling-in-build_backref_tree.patch @@ -0,0 +1,215 @@ +From 75bfb9aff45e44625260f52a5fd581b92ace3e62 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Fri, 19 Sep 2014 10:40:00 -0400 +Subject: Btrfs: cleanup error handling in build_backref_tree + +From: Josef Bacik + +commit 75bfb9aff45e44625260f52a5fd581b92ace3e62 upstream. + +When balance panics it tends to panic in the + +BUG_ON(!upper->checked); + +test, because it means it couldn't build the backref tree properly. This is +annoying to users and frankly a recoverable error, nothing in this function is +actually fatal since it is just an in-memory building of the backrefs for a +given bytenr. So go through and change all the BUG_ON()'s to ASSERT()'s, and +fix the BUG_ON(!upper->checked) thing to just return an error. + +This patch also fixes the error handling so it tears down the work we've done +properly. This code was horribly broken since we always just panic'ed instead +of actually erroring out, so it needed to be completely re-worked. With this +patch my broken image no longer panics when I mount it. Thanks, + +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/relocation.c | 88 +++++++++++++++++++++++++++++++++----------------- + 1 file changed, 59 insertions(+), 29 deletions(-) + +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -736,7 +736,8 @@ again: + err = ret; + goto out; + } +- BUG_ON(!ret || !path1->slots[0]); ++ ASSERT(ret); ++ ASSERT(path1->slots[0]); + + path1->slots[0]--; + +@@ -746,10 +747,10 @@ again: + * the backref was added previously when processing + * backref of type BTRFS_TREE_BLOCK_REF_KEY + */ +- BUG_ON(!list_is_singular(&cur->upper)); ++ ASSERT(list_is_singular(&cur->upper)); + edge = list_entry(cur->upper.next, struct backref_edge, + list[LOWER]); +- BUG_ON(!list_empty(&edge->list[UPPER])); ++ ASSERT(list_empty(&edge->list[UPPER])); + exist = edge->node[UPPER]; + /* + * add the upper level block to pending list if we need +@@ -831,7 +832,7 @@ again: + cur->cowonly = 1; + } + #else +- BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY); ++ ASSERT(key.type != BTRFS_EXTENT_REF_V0_KEY); + if (key.type == BTRFS_SHARED_BLOCK_REF_KEY) { + #endif + if (key.objectid == key.offset) { +@@ -840,7 +841,7 @@ again: + * backref of this type. + */ + root = find_reloc_root(rc, cur->bytenr); +- BUG_ON(!root); ++ ASSERT(root); + cur->root = root; + break; + } +@@ -868,7 +869,7 @@ again: + } else { + upper = rb_entry(rb_node, struct backref_node, + rb_node); +- BUG_ON(!upper->checked); ++ ASSERT(upper->checked); + INIT_LIST_HEAD(&edge->list[UPPER]); + } + list_add_tail(&edge->list[LOWER], &cur->upper); +@@ -892,7 +893,7 @@ again: + + if (btrfs_root_level(&root->root_item) == cur->level) { + /* tree root */ +- BUG_ON(btrfs_root_bytenr(&root->root_item) != ++ ASSERT(btrfs_root_bytenr(&root->root_item) == + cur->bytenr); + if (should_ignore_root(root)) + list_add(&cur->list, &useless); +@@ -927,7 +928,7 @@ again: + need_check = true; + for (; level < BTRFS_MAX_LEVEL; level++) { + if (!path2->nodes[level]) { +- BUG_ON(btrfs_root_bytenr(&root->root_item) != ++ ASSERT(btrfs_root_bytenr(&root->root_item) == + lower->bytenr); + if (should_ignore_root(root)) + list_add(&lower->list, &useless); +@@ -982,7 +983,7 @@ again: + } else { + upper = rb_entry(rb_node, struct backref_node, + rb_node); +- BUG_ON(!upper->checked); ++ ASSERT(upper->checked); + INIT_LIST_HEAD(&edge->list[UPPER]); + if (!upper->owner) + upper->owner = btrfs_header_owner(eb); +@@ -1026,7 +1027,7 @@ next: + * everything goes well, connect backref nodes and insert backref nodes + * into the cache. + */ +- BUG_ON(!node->checked); ++ ASSERT(node->checked); + cowonly = node->cowonly; + if (!cowonly) { + rb_node = tree_insert(&cache->rb_root, node->bytenr, +@@ -1062,8 +1063,21 @@ next: + continue; + } + +- BUG_ON(!upper->checked); +- BUG_ON(cowonly != upper->cowonly); ++ if (!upper->checked) { ++ /* ++ * Still want to blow up for developers since this is a ++ * logic bug. ++ */ ++ ASSERT(0); ++ err = -EINVAL; ++ goto out; ++ } ++ if (cowonly != upper->cowonly) { ++ ASSERT(0); ++ err = -EINVAL; ++ goto out; ++ } ++ + if (!cowonly) { + rb_node = tree_insert(&cache->rb_root, upper->bytenr, + &upper->rb_node); +@@ -1086,7 +1100,7 @@ next: + while (!list_empty(&useless)) { + upper = list_entry(useless.next, struct backref_node, list); + list_del_init(&upper->list); +- BUG_ON(!list_empty(&upper->upper)); ++ ASSERT(list_empty(&upper->upper)); + if (upper == node) + node = NULL; + if (upper->lowest) { +@@ -1119,29 +1133,45 @@ out: + if (err) { + while (!list_empty(&useless)) { + lower = list_entry(useless.next, +- struct backref_node, upper); +- list_del_init(&lower->upper); ++ struct backref_node, list); ++ list_del_init(&lower->list); + } +- upper = node; +- INIT_LIST_HEAD(&list); +- while (upper) { +- if (RB_EMPTY_NODE(&upper->rb_node)) { +- list_splice_tail(&upper->upper, &list); +- free_backref_node(cache, upper); +- } +- +- if (list_empty(&list)) +- break; +- +- edge = list_entry(list.next, struct backref_edge, +- list[LOWER]); ++ while (!list_empty(&list)) { ++ edge = list_first_entry(&list, struct backref_edge, ++ list[UPPER]); ++ list_del(&edge->list[UPPER]); + list_del(&edge->list[LOWER]); ++ lower = edge->node[LOWER]; + upper = edge->node[UPPER]; + free_backref_edge(cache, edge); ++ ++ /* ++ * Lower is no longer linked to any upper backref nodes ++ * and isn't in the cache, we can free it ourselves. ++ */ ++ if (list_empty(&lower->upper) && ++ RB_EMPTY_NODE(&lower->rb_node)) ++ list_add(&lower->list, &useless); ++ ++ if (!RB_EMPTY_NODE(&upper->rb_node)) ++ continue; ++ ++ /* Add this guy's upper edges to the list to proces */ ++ list_for_each_entry(edge, &upper->upper, list[LOWER]) ++ list_add_tail(&edge->list[UPPER], &list); ++ if (list_empty(&upper->upper)) ++ list_add(&upper->list, &useless); ++ } ++ ++ while (!list_empty(&useless)) { ++ lower = list_entry(useless.next, ++ struct backref_node, list); ++ list_del_init(&lower->list); ++ free_backref_node(cache, lower); + } + return ERR_PTR(err); + } +- BUG_ON(node && node->detached); ++ ASSERT(!node || !node->detached); + return node; + } + diff --git a/queue-3.16/btrfs-don-t-do-async-reclaim-during-log-replay.patch b/queue-3.16/btrfs-don-t-do-async-reclaim-during-log-replay.patch new file mode 100644 index 00000000000..44c7c8e5a74 --- /dev/null +++ b/queue-3.16/btrfs-don-t-do-async-reclaim-during-log-replay.patch @@ -0,0 +1,39 @@ +From f6acfd50110b335c7af636cf1fc8e55319cae5fc Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Thu, 18 Sep 2014 11:27:17 -0400 +Subject: Btrfs: don't do async reclaim during log replay + +From: Josef Bacik + +commit f6acfd50110b335c7af636cf1fc8e55319cae5fc upstream. + +Trying to reproduce a log enospc bug I hit a panic in the async reclaim code +during log replay. This is because we use fs_info->fs_root as our root for +shrinking and such. Technically we can use whatever root we want, but let's +just not allow async reclaim while we're doing log replay. Thanks, + +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent-tree.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4508,7 +4508,13 @@ again: + space_info->flush = 1; + } else if (!ret && space_info->flags & BTRFS_BLOCK_GROUP_METADATA) { + used += orig_bytes; +- if (need_do_async_reclaim(space_info, root->fs_info, used) && ++ /* ++ * We will do the space reservation dance during log replay, ++ * which means we won't have fs_info->fs_root set, so don't do ++ * the async reclaim as we will panic. ++ */ ++ if (!root->fs_info->log_root_recovering && ++ need_do_async_reclaim(space_info, root->fs_info, used) && + !work_busy(&root->fs_info->async_reclaim_work)) + queue_work(system_unbound_wq, + &root->fs_info->async_reclaim_work); diff --git a/queue-3.16/btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch b/queue-3.16/btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch new file mode 100644 index 00000000000..c1315402907 --- /dev/null +++ b/queue-3.16/btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch @@ -0,0 +1,67 @@ +From 12b894cb288d57292b01cf158177b6d5c89a6272 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Wed, 20 Aug 2014 16:10:15 +0800 +Subject: btrfs: Fix a deadlock in btrfs_dev_replace_finishing() + +From: Qu Wenruo + +commit 12b894cb288d57292b01cf158177b6d5c89a6272 upstream. + +btrfs-transacion:5657 +[stack snip] +btrfs_bio_map() + btrfs_bio_counter_inc_blocked() + percpu_counter_inc(&fs_info->bio_counter) ###bio_counter > 0(A) + __btrfs_bio_map() + btrfs_dev_replace_lock() + mutex_lock(dev_replace->lock) ###wait mutex(B) + +btrfs:32612 +[stack snip] +btrfs_dev_replace_start() + btrfs_dev_replace_lock() + mutex_lock(dev_replace->lock) ###hold mutex(B) + btrfs_dev_replace_finishing() + btrfs_rm_dev_replace_blocked() + wait until percpu_counter_sum == 0 ###wait on bio_counter(A) + +This bug can be triggered quite easily by the following test script: +http://pastebin.com/MQmb37Cy + +This patch will fix the ABBA problem by calling +btrfs_dev_replace_unlock() before btrfs_rm_dev_replace_blocked(). + +The consistency of btrfs devices list and their superblocks is protected +by device_list_mutex, not btrfs_dev_replace_lock/unlock(). +So it is safe the move btrfs_dev_replace_unlock() before +btrfs_rm_dev_replace_blocked(). + +Reported-by: Zhao Lei +Signed-off-by: Qu Wenruo +Cc: Stefan Behrens +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/dev-replace.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/dev-replace.c ++++ b/fs/btrfs/dev-replace.c +@@ -567,6 +567,8 @@ static int btrfs_dev_replace_finishing(s + btrfs_kobj_rm_device(fs_info, src_device); + btrfs_kobj_add_device(fs_info, tgt_device); + ++ btrfs_dev_replace_unlock(dev_replace); ++ + btrfs_rm_dev_replace_blocked(fs_info); + + btrfs_rm_dev_replace_srcdev(fs_info, src_device); +@@ -580,7 +582,6 @@ static int btrfs_dev_replace_finishing(s + * superblock is scratched out so that it is no longer marked to + * belong to this filesystem. + */ +- btrfs_dev_replace_unlock(dev_replace); + mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); + mutex_unlock(&root->fs_info->chunk_mutex); + diff --git a/queue-3.16/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch b/queue-3.16/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch new file mode 100644 index 00000000000..3f5d12ebc95 --- /dev/null +++ b/queue-3.16/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch @@ -0,0 +1,63 @@ +From bbe9051441effce51c9a533d2c56440df64db2d7 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Fri, 19 Sep 2014 15:43:34 -0400 +Subject: Btrfs: fix build_backref_tree issue with multiple shared blocks + +From: Josef Bacik + +commit bbe9051441effce51c9a533d2c56440df64db2d7 upstream. + +Marc Merlin sent me a broken fs image months ago where it would blow up in the +upper->checked BUG_ON() in build_backref_tree. This is because we had a +scenario like this + +block a -- level 4 (not shared) + | +block b -- level 3 (reloc block, shared) + | +block c -- level 2 (not shared) + | +block d -- level 1 (shared) + | +block e -- level 0 (shared) + +We go to build a backref tree for block e, we notice block d is shared and add +it to the list of blocks to lookup it's backrefs for. Now when we loop around +we will check edges for the block, so we will see we looked up block c last +time. So we lookup block d and then see that the block that points to it is +block c and we can just skip that edge since we've already been up this path. +The problem is because we clear need_check when we see block d (as it is shared) +we never add block b as needing to be checked. And because block c is in our +path already we bail out before we walk up to block b and add it to the backref +check list. + +To fix this we need to reset need_check if we trip over a block that doesn't +need to be checked. This will make sure that any subsequent blocks in the path +as we're walking up afterwards are added to the list to be processed. With this +patch I can now mount Marc's fs image and it'll complete the balance without +panicing. Thanks, + +Reported-by: Marc MERLIN +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/relocation.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -978,8 +978,11 @@ again: + need_check = false; + list_add_tail(&edge->list[UPPER], + &list); +- } else ++ } else { ++ if (upper->checked) ++ need_check = true; + INIT_LIST_HEAD(&edge->list[UPPER]); ++ } + } else { + upper = rb_entry(rb_node, struct backref_node, + rb_node); diff --git a/queue-3.16/btrfs-fix-race-in-wait_sync-ioctl.patch b/queue-3.16/btrfs-fix-race-in-wait_sync-ioctl.patch new file mode 100644 index 00000000000..dc00af6c422 --- /dev/null +++ b/queue-3.16/btrfs-fix-race-in-wait_sync-ioctl.patch @@ -0,0 +1,56 @@ +From 42383020beb1cfb05f5d330cc311931bc4917a97 Mon Sep 17 00:00:00 2001 +From: Sage Weil +Date: Fri, 26 Sep 2014 08:30:06 -0700 +Subject: Btrfs: fix race in WAIT_SYNC ioctl + +From: Sage Weil + +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 +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-3.16/btrfs-fix-up-bounds-checking-in-lseek.patch b/queue-3.16/btrfs-fix-up-bounds-checking-in-lseek.patch new file mode 100644 index 00000000000..f3eab46a576 --- /dev/null +++ b/queue-3.16/btrfs-fix-up-bounds-checking-in-lseek.patch @@ -0,0 +1,88 @@ +From 4d1a40c66bed0b3fa43b9da5fbd5cbe332e4eccf Mon Sep 17 00:00:00 2001 +From: Liu Bo +Date: Tue, 16 Sep 2014 17:49:30 +0800 +Subject: Btrfs: fix up bounds checking in lseek +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Liu Bo + +commit 4d1a40c66bed0b3fa43b9da5fbd5cbe332e4eccf upstream. + +An user reported this, it is because that lseek's SEEK_SET/SEEK_CUR/SEEK_END +allow a negative value for @offset, but btrfs's SEEK_DATA/SEEK_HOLE don't +prepare for that and convert the negative @offset into unsigned type, +so we get (end < start) warning. + +[ 1269.835374] ------------[ cut here ]------------ +[ 1269.836809] WARNING: CPU: 0 PID: 1241 at fs/btrfs/extent_io.c:430 insert_state+0x11d/0x140() +[ 1269.838816] BTRFS: end < start 4094 18446744073709551615 +[ 1269.840334] CPU: 0 PID: 1241 Comm: a.out Tainted: G W 3.16.0+ #306 +[ 1269.858229] Call Trace: +[ 1269.858612] [] dump_stack+0x4e/0x68 +[ 1269.858952] [] warn_slowpath_common+0x8c/0xc0 +[ 1269.859416] [] warn_slowpath_fmt+0x46/0x50 +[ 1269.859929] [] insert_state+0x11d/0x140 +[ 1269.860409] [] __set_extent_bit+0x3b6/0x4e0 +[ 1269.860805] [] lock_extent_bits+0x87/0x200 +[ 1269.861697] [] btrfs_file_llseek+0x148/0x2a0 +[ 1269.862168] [] SyS_lseek+0xae/0xc0 +[ 1269.862620] [] system_call_fastpath+0x16/0x1b +[ 1269.862970] ---[ end trace 4d33ea885832054b ]--- + +This assumes that btrfs starts finding DATA/HOLE from the beginning of file +if the assigned @offset is negative. + +Also we add alignment for lock_extent_bits 's range. + +Reported-by: Toralf Förster +Signed-off-by: Liu Bo +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/file.c | 25 +++++++++++++++---------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -2622,23 +2622,28 @@ static int find_desired_extent(struct in + struct btrfs_root *root = BTRFS_I(inode)->root; + struct extent_map *em = NULL; + struct extent_state *cached_state = NULL; +- u64 lockstart = *offset; +- u64 lockend = i_size_read(inode); +- u64 start = *offset; +- u64 len = i_size_read(inode); ++ u64 lockstart; ++ u64 lockend; ++ u64 start; ++ u64 len; + int ret = 0; + +- lockend = max_t(u64, root->sectorsize, lockend); ++ if (inode->i_size == 0) ++ return -ENXIO; ++ ++ /* ++ * *offset can be negative, in this case we start finding DATA/HOLE from ++ * the very start of the file. ++ */ ++ start = max_t(loff_t, 0, *offset); ++ ++ lockstart = round_down(start, root->sectorsize); ++ lockend = round_up(i_size_read(inode), root->sectorsize); + if (lockend <= lockstart) + lockend = lockstart + root->sectorsize; +- + lockend--; + len = lockend - lockstart + 1; + +- len = max_t(u64, len, root->sectorsize); +- if (inode->i_size == 0) +- return -ENXIO; +- + lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0, + &cached_state); + diff --git a/queue-3.16/btrfs-try-not-to-enospc-on-log-replay.patch b/queue-3.16/btrfs-try-not-to-enospc-on-log-replay.patch new file mode 100644 index 00000000000..70c621c9a35 --- /dev/null +++ b/queue-3.16/btrfs-try-not-to-enospc-on-log-replay.patch @@ -0,0 +1,40 @@ +From 1d52c78afbbf80b58299e076a159617d6b42fe3c Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Thu, 18 Sep 2014 11:30:44 -0400 +Subject: Btrfs: try not to ENOSPC on log replay + +From: Josef Bacik + +commit 1d52c78afbbf80b58299e076a159617d6b42fe3c upstream. + +When doing log replay we may have to update inodes, which traditionally goes +through our delayed inode stuff. This will try to move space over from the +trans handle, but we don't reserve space in our trans handle on replay since we +don't know how much we will need, so instead we try to flush. But because we +have a trans handle open we won't flush anything, so if we are out of reserve +space we will simply return ENOSPC. Since we know that if an operation made it +into the log then we definitely had space before the box bought the farm then we +don't need to worry about doing this space reservation. Use the +fs_info->log_root_recovering flag to skip the delayed inode stuff and update the +item directly. Thanks, + +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/inode.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3656,7 +3656,8 @@ noinline int btrfs_update_inode(struct b + * without delay + */ + if (!btrfs_is_free_space_inode(inode) +- && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { ++ && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID ++ && !root->fs_info->log_root_recovering) { + btrfs_update_root_times(trans, root); + + ret = btrfs_delayed_update_inode(trans, root, inode); diff --git a/queue-3.16/btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch b/queue-3.16/btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch new file mode 100644 index 00000000000..f7cdc1fc335 --- /dev/null +++ b/queue-3.16/btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch @@ -0,0 +1,39 @@ +From 2fad4e83e12591eb3bd213875b9edc2d18e93383 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Wed, 23 Jul 2014 14:39:35 +0200 +Subject: btrfs: wake up transaction thread from SYNC_FS ioctl + +From: David Sterba + +commit 2fad4e83e12591eb3bd213875b9edc2d18e93383 upstream. + +The transaction thread may want to do more work, namely it pokes the +cleaner ktread that will start processing uncleaned subvols. + +This can be triggered by user via the 'btrfs fi sync' command, otherwise +there was a delay up to 30 seconds before the cleaner started to clean +old snapshots. + +Signed-off-by: David Sterba +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/ioctl.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -5309,6 +5309,12 @@ long btrfs_ioctl(struct file *file, unsi + if (ret) + return ret; + ret = btrfs_sync_fs(file->f_dentry->d_sb, 1); ++ /* ++ * The transaction thread may want to do more work, ++ * namely it pokes the cleaner ktread that will start ++ * processing uncleaned subvols. ++ */ ++ wake_up_process(root->fs_info->transaction_kthread); + return ret; + } + case BTRFS_IOC_START_SYNC: diff --git a/queue-3.16/series b/queue-3.16/series index 19607c0b9ad..d70c95e8b70 100644 --- a/queue-3.16/series +++ b/queue-3.16/series @@ -1 +1,9 @@ btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch +btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch +btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch +btrfs-fix-up-bounds-checking-in-lseek.patch +btrfs-don-t-do-async-reclaim-during-log-replay.patch +btrfs-try-not-to-enospc-on-log-replay.patch +btrfs-cleanup-error-handling-in-build_backref_tree.patch +btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch +btrfs-fix-race-in-wait_sync-ioctl.patch -- 2.47.3