FAILED: patch "[PATCH] btrfs: qgroup: Prevent qgroup->reserved from going subzero" failed to apply to 4.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
0b34c261e235a5c74dcf78bd305845bd15fe2b42Mon Sep 17 00:00:00 2001
From: Goldwyn Rodrigues <[email protected]>
Date: Fri, 30 Sep 2016 10:40:52 -0500
Subject: [PATCH] btrfs: qgroup: Prevent qgroup->reserved from going subzero
While free'ing qgroup->reserved resources, we much check if the page has not been invalidated by a truncate operation by checking if the page is still dirty before reducing the qgroup resources. Resources in such a case are free'd when the entire extent is released by delayed_ref.
This fixes a double accounting while releasing resources in case of truncating a file, reproduced by the following testcase.
SCRATCH_DEV=/dev/vdb
SCRATCH_MNT=/mnt
mkfs.btrfs -f $SCRATCH_DEV
mount -t btrfs $SCRATCH_DEV $SCRATCH_MNT
cd $SCRATCH_MNT
btrfs quota enable $SCRATCH_MNT
btrfs subvolume create a
btrfs qgroup limit 500m a $SCRATCH_MNT
sync
for c in {1..15}; do
dd if=/dev/zero bs=1M count=40 of=$SCRATCH_MNT/a/file; done
sleep 10
sync
sleep 5
touch $SCRATCH_MNT/a/newfile
echo "Removing file"
rm $SCRATCH_MNT/a/file
fs/btrfs/inode.c +7 -2
@@ -8930,9 +8930,14 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,* So even we call qgroup_free_data(), it won't decrease reserved * space. * 2) Not written to disk -* This means the reserved space should be freed here. +* This means the reserved space should be freed here. However, +* if a truncate invalidates the page (by clearing PageDirty) +* and the page is accounted for while allocating extent +* in btrfs_check_data_free_space() we let delayed_ref to +* free the entire extent. */ -btrfs_qgroup_free_data (inode, page_start,PAGE_SIZE ); +if (PageDirty (page)) +btrfs_qgroup_free_data (inode, page_start,PAGE_SIZE );if (!inode_evicting) { clear_extent_bit(tree, page_start, page_end, EXTENT_LOCKED | EXTENT_DIRTY |