| From 113e8283869b9855c8b999796aadd506bbac155f Mon Sep 17 00:00:00 2001 |
| From: Filipe Manana <fdmanana@suse.com> |
| Date: Mon, 30 Mar 2015 18:26:47 +0100 |
| Subject: Btrfs: fix inode eviction infinite loop after extent_same ioctl |
| |
| From: Filipe Manana <fdmanana@suse.com> |
| |
| commit 113e8283869b9855c8b999796aadd506bbac155f upstream. |
| |
| If we pass a length of 0 to the extent_same ioctl, we end up locking an |
| extent range with a start offset greater then its end offset (if the |
| destination file's offset is greater than zero). This results in a warning |
| from extent_io.c:insert_state through the following call chain: |
| |
| btrfs_extent_same() |
| btrfs_double_lock() |
| lock_extent_range() |
| lock_extent(inode->io_tree, offset, offset + len - 1) |
| lock_extent_bits() |
| __set_extent_bit() |
| insert_state() |
| --> WARN_ON(end < start) |
| |
| This leads to an infinite loop when evicting the inode. This is the same |
| problem that my previous patch titled |
| "Btrfs: fix inode eviction infinite loop after cloning into it" addressed |
| but for the extent_same ioctl instead of the clone ioctl. |
| |
| Signed-off-by: Filipe Manana <fdmanana@suse.com> |
| Reviewed-by: Omar Sandoval <osandov@osandov.com> |
| Signed-off-by: Chris Mason <clm@fb.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/btrfs/ioctl.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/fs/btrfs/ioctl.c |
| +++ b/fs/btrfs/ioctl.c |
| @@ -2897,6 +2897,9 @@ static int btrfs_extent_same(struct inod |
| if (src == dst) |
| return -EINVAL; |
| |
| + if (len == 0) |
| + return 0; |
| + |
| btrfs_double_lock(src, loff, dst, dst_loff, len); |
| |
| ret = extent_same_check_offsets(src, loff, len); |