| From 2cc8334270e281815c3850c3adea363c51f21e0d Mon Sep 17 00:00:00 2001 |
| From: Josef Bacik <josef@toxicpanda.com> |
| Date: Wed, 6 Mar 2019 17:13:04 -0500 |
| Subject: btrfs: remove WARN_ON in log_dir_items |
| |
| From: Josef Bacik <josef@toxicpanda.com> |
| |
| commit 2cc8334270e281815c3850c3adea363c51f21e0d upstream. |
| |
| When Filipe added the recursive directory logging stuff in |
| 2f2ff0ee5e430 ("Btrfs: fix metadata inconsistencies after directory |
| fsync") he specifically didn't take the directory i_mutex for the |
| children directories that we need to log because of lockdep. This is |
| generally fine, but can lead to this WARN_ON() tripping if we happen to |
| run delayed deletion's in between our first search and our second search |
| of dir_item/dir_indexes for this directory. We expect this to happen, |
| so the WARN_ON() isn't necessary. Drop the WARN_ON() and add a comment |
| so we know why this case can happen. |
| |
| CC: stable@vger.kernel.org # 4.4+ |
| Reviewed-by: Filipe Manana <fdmanana@suse.com> |
| Signed-off-by: Josef Bacik <josef@toxicpanda.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/btrfs/tree-log.c | 11 +++++++++-- |
| 1 file changed, 9 insertions(+), 2 deletions(-) |
| |
| --- a/fs/btrfs/tree-log.c |
| +++ b/fs/btrfs/tree-log.c |
| @@ -3422,9 +3422,16 @@ static noinline int log_dir_items(struct |
| } |
| btrfs_release_path(path); |
| |
| - /* find the first key from this transaction again */ |
| + /* |
| + * Find the first key from this transaction again. See the note for |
| + * log_new_dir_dentries, if we're logging a directory recursively we |
| + * won't be holding its i_mutex, which means we can modify the directory |
| + * while we're logging it. If we remove an entry between our first |
| + * search and this search we'll not find the key again and can just |
| + * bail. |
| + */ |
| ret = btrfs_search_slot(NULL, root, &min_key, path, 0, 0); |
| - if (WARN_ON(ret != 0)) |
| + if (ret != 0) |
| goto done; |
| |
| /* |