kernel-fxtec-pro1x/fs/btrfs
Qu Wenruo 803b2f2f9c btrfs: qgroup: fix data leak caused by race between writeback and truncate
[ Upstream commit fa91e4aa1716004ea8096d5185ec0451e206aea0 ]

[BUG]
When running tests like generic/013 on test device with btrfs quota
enabled, it can normally lead to data leak, detected at unmount time:

  BTRFS warning (device dm-3): qgroup 0/5 has unreleased space, type 0 rsv 4096
  ------------[ cut here ]------------
  WARNING: CPU: 11 PID: 16386 at fs/btrfs/disk-io.c:4142 close_ctree+0x1dc/0x323 [btrfs]
  RIP: 0010:close_ctree+0x1dc/0x323 [btrfs]
  Call Trace:
   btrfs_put_super+0x15/0x17 [btrfs]
   generic_shutdown_super+0x72/0x110
   kill_anon_super+0x18/0x30
   btrfs_kill_super+0x17/0x30 [btrfs]
   deactivate_locked_super+0x3b/0xa0
   deactivate_super+0x40/0x50
   cleanup_mnt+0x135/0x190
   __cleanup_mnt+0x12/0x20
   task_work_run+0x64/0xb0
   __prepare_exit_to_usermode+0x1bc/0x1c0
   __syscall_return_slowpath+0x47/0x230
   do_syscall_64+0x64/0xb0
   entry_SYSCALL_64_after_hwframe+0x44/0xa9
  ---[ end trace caf08beafeca2392 ]---
  BTRFS error (device dm-3): qgroup reserved space leaked

[CAUSE]
In the offending case, the offending operations are:
2/6: writev f2X[269 1 0 0 0 0] [1006997,67,288] 0
2/7: truncate f2X[269 1 0 0 48 1026293] 18388 0

The following sequence of events could happen after the writev():
	CPU1 (writeback)		|		CPU2 (truncate)
-----------------------------------------------------------------
btrfs_writepages()			|
|- extent_write_cache_pages()		|
   |- Got page for 1003520		|
   |  1003520 is Dirty, no writeback	|
   |  So (!clear_page_dirty_for_io())   |
   |  gets called for it		|
   |- Now page 1003520 is Clean.	|
   |					| btrfs_setattr()
   |					| |- btrfs_setsize()
   |					|    |- truncate_setsize()
   |					|       New i_size is 18388
   |- __extent_writepage()		|
   |  |- page_offset() > i_size		|
      |- btrfs_invalidatepage()		|
	 |- Page is clean, so no qgroup |
	    callback executed

This means, the qgroup reserved data space is not properly released in
btrfs_invalidatepage() as the page is Clean.

[FIX]
Instead of checking the dirty bit of a page, call
btrfs_qgroup_free_data() unconditionally in btrfs_invalidatepage().

As qgroup rsv are completely bound to the QGROUP_RESERVED bit of
io_tree, not bound to page status, thus we won't cause double freeing
anyway.

Fixes: 0b34c261e2 ("btrfs: qgroup: Prevent qgroup->reserved from going subzero")
CC: stable@vger.kernel.org # 4.14+
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-10-01 13:14:49 +02:00
..
tests Btrfs: fix selftests failure due to uninitialized i_mode in test inodes 2020-08-05 10:06:00 +02:00
acl.c
async-thread.c Btrfs: fix crash during unmount due to race with delayed inode workers 2020-04-17 10:48:49 +02:00
async-thread.h Btrfs: fix crash during unmount due to race with delayed inode workers 2020-04-17 10:48:49 +02:00
backref.c btrfs: fix double free on ulist after backref resolution failure 2020-07-29 10:16:47 +02:00
backref.h
btrfs_inode.h
check-integrity.c btrfs: fix possible NULL-pointer dereference in integrity checks 2020-02-24 08:34:49 +01:00
check-integrity.h
compression.c btrfs: correctly validate compression type 2019-09-16 08:22:19 +02:00
compression.h btrfs: correctly validate compression type 2019-09-16 08:22:19 +02:00
ctree.c btrfs: set the lockdep class for log tree extent buffers 2020-09-09 19:04:29 +02:00
ctree.h btrfs: export helpers for subvolume name/id resolution 2020-08-26 10:30:58 +02:00
dedupe.h
delayed-inode.c btrfs: use nofs allocations for running delayed items 2020-04-17 10:48:54 +02:00
delayed-inode.h
delayed-ref.c Btrfs: fix race between adding and putting tree mod seq elements and nodes 2020-02-11 04:34:06 -08:00
delayed-ref.h
dev-replace.c btrfs: merge btrfs_find_device and find_device 2020-06-22 09:04:59 +02:00
dev-replace.h
dir-item.c
disk-io.c btrfs: fix space cache memory leak after transaction abort 2020-09-03 11:24:26 +02:00
disk-io.h
export.c btrfs: export helpers for subvolume name/id resolution 2020-08-26 10:30:58 +02:00
export.h btrfs: export helpers for subvolume name/id resolution 2020-08-26 10:30:58 +02:00
extent-tree.c btrfs: don't force read-only after error in drop snapshot 2020-10-01 13:14:46 +02:00
extent_io.c btrfs: fix potential deadlock in the search ioctl 2020-09-09 19:04:29 +02:00
extent_io.h btrfs: fix potential deadlock in the search ioctl 2020-09-09 19:04:29 +02:00
extent_map.c Btrfs: fix race between using extent maps and merging them 2020-02-19 19:51:56 +01:00
extent_map.h
file-item.c btrfs: do not ignore error from btrfs_next_leaf() when inserting checksums 2020-06-22 09:05:11 +02:00
file.c btrfs: file: reserve qgroup space after the hole punch range is locked 2020-09-03 11:24:22 +02:00
free-space-cache.c btrfs: fix space cache memory leak after transaction abort 2020-09-03 11:24:26 +02:00
free-space-cache.h
free-space-tree.c
free-space-tree.h
inode-item.c
inode-map.c Btrfs: fix inode cache waiters hanging on path allocation failure 2020-01-27 14:51:12 +01:00
inode-map.h
inode.c btrfs: qgroup: fix data leak caused by race between writeback and truncate 2020-10-01 13:14:49 +02:00
ioctl.c btrfs: fix wrong address when faulting in pages in the search ioctl 2020-09-17 13:45:28 +02:00
Kconfig
locking.c
locking.h
lzo.c
Makefile
math.h
ordered-data.c Btrfs: fix btrfs_wait_ordered_range() so that it waits for all ordered extents 2020-02-28 16:38:58 +01:00
ordered-data.h
orphan.c
print-tree.c btrfs: require only sector size alignment for parent eb bytenr 2020-09-17 13:45:28 +02:00
print-tree.h
props.c btrfs: correctly validate compression type 2019-09-16 08:22:19 +02:00
props.h
qgroup.c btrfs: qgroup: mark qgroup inconsistent if we're inherting snapshot to a new qgroup 2020-06-22 09:05:19 +02:00
qgroup.h
raid56.c
raid56.h
rcu-string.h
reada.c btrfs: don't prematurely free work in reada_start_machine_worker() 2019-12-31 16:36:16 +01:00
ref-verify.c btrfs: ref-verify: fix memory leak in add_block_entry 2020-08-21 11:05:30 +02:00
ref-verify.h
relocation.c btrfs: check commit root generation in should_ignore_root 2020-04-21 09:03:09 +02:00
root-tree.c btrfs: do not delete mismatched root refs 2020-01-23 08:21:31 +01:00
scrub.c btrfs: merge btrfs_find_device and find_device 2020-06-22 09:04:59 +02:00
send.c btrfs: send: emit file capabilities after chown 2020-06-22 09:05:21 +02:00
send.h
struct-funcs.c
super.c btrfs: reset compression level for lzo on remount 2020-09-03 11:24:26 +02:00
sysfs.c btrfs: sysfs: use NOFS for device creation 2020-08-26 10:30:59 +02:00
sysfs.h
transaction.c btrfs: transaction: Avoid deadlock due to bad initialization timing of fs_info::journal_info 2020-05-06 08:13:33 +02:00
transaction.h Btrfs: fix deadlock between fiemap and transaction commits 2019-08-25 10:47:54 +02:00
tree-checker.c btrfs: tree-checker: Check level for leaves and nodes 2020-06-22 09:05:01 +02:00
tree-checker.h
tree-defrag.c
tree-log.c btrfs: check the right error variable in btrfs_del_dir_entries_in_log 2020-09-03 11:24:31 +02:00
tree-log.h
ulist.c
ulist.h
uuid-tree.c btrfs: handle ENOENT in btrfs_uuid_tree_iterate 2019-12-31 16:34:44 +01:00
volumes.c btrfs: fix lockdep splat in add_missing_dev 2020-09-17 13:45:28 +02:00
volumes.h btrfs: merge btrfs_find_device and find_device 2020-06-22 09:04:59 +02:00
xattr.c
xattr.h
zlib.c
zstd.c