<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel.git/fs/btrfs/extent-tree.c, branch linux-3.4.y</title>
<subtitle>Hosts the 0x221E linux distro kernel.
</subtitle>
<id>https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-3.4.y</id>
<link rel='self' href='https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-3.4.y'/>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/'/>
<updated>2015-09-18T01:20:26Z</updated>
<entry>
<title>Btrfs: fix log tree corruption when fs mounted with -o discard</title>
<updated>2015-09-18T01:20:26Z</updated>
<author>
<name>Filipe Manana</name>
</author>
<published>2015-03-23T14:07:40Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=abe62247e0fd8ae561d13d803267241143ececa1'/>
<id>urn:sha1:abe62247e0fd8ae561d13d803267241143ececa1</id>
<content type='text'>
commit dcc82f4783ad91d4ab654f89f37ae9291cdc846a upstream.

While committing a transaction we free the log roots before we write the
new super block. Freeing the log roots implies marking the disk location
of every node/leaf (metadata extent) as pinned before the new super block
is written. This is to prevent the disk location of log metadata extents
from being reused before the new super block is written, otherwise we
would have a corrupted log tree if before the new super block is written
a crash/reboot happens and the location of any log tree metadata extent
ended up being reused and rewritten.

Even though we pinned the log tree's metadata extents, we were issuing a
discard against them if the fs was mounted with the -o discard option,
resulting in corruption of the log tree if a crash/reboot happened before
writing the new super block - the next time the fs was mounted, during
the log replay process we would find nodes/leafs of the log btree with
a content full of zeroes, causing the process to fail and require the
use of the tool btrfs-zero-log to wipeout the log tree (and all data
previously fsynced becoming lost forever).

Fix this by not doing a discard when pinning an extent. The discard will
be done later when it's safe (after the new super block is committed) at
extent-tree.c:btrfs_finish_extent_commit().

Fixes: e688b7252f78 (Btrfs: fix extent pinning bugs in the tree log)
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
Signed-off-by: Zefan Li &lt;lizefan@huawei.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix fs corruption on transaction abort if device supports discard</title>
<updated>2015-04-14T09:33:45Z</updated>
<author>
<name>Filipe Manana</name>
</author>
<published>2014-12-07T21:31:47Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=11b814e3597eeffa475e2e41323aa52d2e2289fa'/>
<id>urn:sha1:11b814e3597eeffa475e2e41323aa52d2e2289fa</id>
<content type='text'>
commit 678886bdc6378c1cbd5072da2c5a3035000214e3 upstream.

When we abort a transaction we iterate over all the ranges marked as dirty
in fs_info-&gt;freed_extents[0] and fs_info-&gt;freed_extents[1], clear them
from those trees, add them back (unpin) to the free space caches and, if
the fs was mounted with "-o discard", perform a discard on those regions.
Also, after adding the regions to the free space caches, a fitrim ioctl call
can see those ranges in a block group's free space cache and perform a discard
on the ranges, so the same issue can happen without "-o discard" as well.

This causes corruption, affecting one or multiple btree nodes (in the worst
case leaving the fs unmountable) because some of those ranges (the ones in
the fs_info-&gt;pinned_extents tree) correspond to btree nodes/leafs that are
referred by the last committed super block - breaking the rule that anything
that was committed by a transaction is untouched until the next transaction
commits successfully.

I ran into this while running in a loop (for several hours) the fstest that
I recently submitted:

  [PATCH] fstests: add btrfs test to stress chunk allocation/removal and fstrim

The corruption always happened when a transaction aborted and then fsck complained
like this:

   _check_btrfs_filesystem: filesystem on /dev/sdc is inconsistent
   *** fsck.btrfs output ***
   Check tree block failed, want=94945280, have=0
   Check tree block failed, want=94945280, have=0
   Check tree block failed, want=94945280, have=0
   Check tree block failed, want=94945280, have=0
   Check tree block failed, want=94945280, have=0
   read block failed check_tree_block
   Couldn't open file system

In this case 94945280 corresponded to the root of a tree.
Using frace what I observed was the following sequence of steps happened:

   1) transaction N started, fs_info-&gt;pinned_extents pointed to
      fs_info-&gt;freed_extents[0];

   2) node/eb 94945280 is created;

   3) eb is persisted to disk;

   4) transaction N commit starts, fs_info-&gt;pinned_extents now points to
      fs_info-&gt;freed_extents[1], and transaction N completes;

   5) transaction N + 1 starts;

   6) eb is COWed, and btrfs_free_tree_block() called for this eb;

   7) eb range (94945280 to 94945280 + 16Kb) is added to
      fs_info-&gt;pinned_extents (fs_info-&gt;freed_extents[1]);

   8) Something goes wrong in transaction N + 1, like hitting ENOSPC
      for example, and the transaction is aborted, turning the fs into
      readonly mode. The stack trace I got for example:

      [112065.253935]  [&lt;ffffffff8140c7b6&gt;] dump_stack+0x4d/0x66
      [112065.254271]  [&lt;ffffffff81042984&gt;] warn_slowpath_common+0x7f/0x98
      [112065.254567]  [&lt;ffffffffa0325990&gt;] ? __btrfs_abort_transaction+0x50/0x10b [btrfs]
      [112065.261674]  [&lt;ffffffff810429e5&gt;] warn_slowpath_fmt+0x48/0x50
      [112065.261922]  [&lt;ffffffffa032949e&gt;] ? btrfs_free_path+0x26/0x29 [btrfs]
      [112065.262211]  [&lt;ffffffffa0325990&gt;] __btrfs_abort_transaction+0x50/0x10b [btrfs]
      [112065.262545]  [&lt;ffffffffa036b1d6&gt;] btrfs_remove_chunk+0x537/0x58b [btrfs]
      [112065.262771]  [&lt;ffffffffa033840f&gt;] btrfs_delete_unused_bgs+0x1de/0x21b [btrfs]
      [112065.263105]  [&lt;ffffffffa0343106&gt;] cleaner_kthread+0x100/0x12f [btrfs]
      (...)
      [112065.264493] ---[ end trace dd7903a975a31a08 ]---
      [112065.264673] BTRFS: error (device sdc) in btrfs_remove_chunk:2625: errno=-28 No space left
      [112065.264997] BTRFS info (device sdc): forced readonly

   9) The clear kthread sees that the BTRFS_FS_STATE_ERROR bit is set in
      fs_info-&gt;fs_state and calls btrfs_cleanup_transaction(), which in
      turn calls btrfs_destroy_pinned_extent();

   10) Then btrfs_destroy_pinned_extent() iterates over all the ranges
       marked as dirty in fs_info-&gt;freed_extents[], and for each one
       it calls discard, if the fs was mounted with "-o discard", and
       adds the range to the free space cache of the respective block
       group;

   11) btrfs_trim_block_group(), invoked from the fitrim ioctl code path,
       sees the free space entries and performs a discard;

   12) After an umount and mount (or fsck), our eb's location on disk was full
       of zeroes, and it should have been untouched, because it was marked as
       dirty in the fs_info-&gt;pinned_extents tree, and therefore used by the
       trees that the last committed superblock points to.

Fix this by not performing a discard and not adding the ranges to the free space
caches - it's useless from this point since the fs is now in readonly mode and
we won't write free space caches to disk anymore (otherwise we would leak space)
nor any new superblock. By not adding the ranges to the free space caches, it
prevents other code paths from allocating that space and write to it as well,
therefore being safer and simpler.

This isn't a new problem, as it's been present since 2011 (git commit
acce952b0263825da32cf10489413dec78053347).

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
Signed-off-by: Zefan Li &lt;lizefan@huawei.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: handle EAGAIN case properly in btrfs_drop_snapshot()</title>
<updated>2014-02-06T19:05:48Z</updated>
<author>
<name>Wang Shilong</name>
</author>
<published>2014-01-07T09:26:58Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=06c23d087a238d3838de9b87c793195daae8a8bc'/>
<id>urn:sha1:06c23d087a238d3838de9b87c793195daae8a8bc</id>
<content type='text'>
commit 90515e7f5d7d24cbb2a4038a3f1b5cfa2921aa17 upstream.

We may return early in btrfs_drop_snapshot(), we shouldn't
call btrfs_std_err() for this case, fix it.

Signed-off-by: Wang Shilong &lt;wangsl.fnst@cn.fujitsu.com&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>Btrfs: re-add root to dead root list if we stop dropping it</title>
<updated>2013-08-04T08:25:54Z</updated>
<author>
<name>Josef Bacik</name>
</author>
<published>2013-07-17T23:30:20Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=e94d695ac4f0f047eef5c5b71dae1c2aefd59def'/>
<id>urn:sha1:e94d695ac4f0f047eef5c5b71dae1c2aefd59def</id>
<content type='text'>
commit d29a9f629e009c9b90e5859bce581070fd6247fc upstream.

If we stop dropping a root for whatever reason we need to add it back to the
dead root list so that we will re-start the dropping next transaction commit.
The other case this happens is if we recover a drop because we will add a root
without adding it to the fs radix tree, so we can leak it's root and commit root
extent buffer, adding this to the dead root list makes this cleanup happen.
Thanks,

Reported-by: Alex Lyakas &lt;alex.btrfs@zadarastorage.com&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fusionio.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>Btrfs: fix lock leak when resuming snapshot deletion</title>
<updated>2013-08-04T08:25:54Z</updated>
<author>
<name>Josef Bacik</name>
</author>
<published>2013-07-15T16:41:42Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=849f48aea9edb426a418b7b38f5c903fcc84fdf5'/>
<id>urn:sha1:849f48aea9edb426a418b7b38f5c903fcc84fdf5</id>
<content type='text'>
commit fec386ac1428f9c0e672df952cbca5cebd4e4e2f upstream.

We aren't setting path-&gt;locks[level] when we resume a snapshot deletion which
means we won't unlock the buffer when we free the path.  This causes deadlocks
if we happen to re-allocate the block before we've evicted the extent buffer
from cache.  Thanks,

Reported-by: Alex Lyakas &lt;alex.btrfs@zadarastorage.com&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fusionio.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>Btrfs: fix space leak when we fail to reserve metadata space</title>
<updated>2013-04-05T17:04:36Z</updated>
<author>
<name>Josef Bacik</name>
</author>
<published>2013-03-25T20:03:35Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=2ee4a8e3c9b8225703611097a0a410ca52de3d51'/>
<id>urn:sha1:2ee4a8e3c9b8225703611097a0a410ca52de3d51</id>
<content type='text'>
commit f4881bc7a83eff263789dd524b7c269d138d4af5 upstream.

Dave reported a warning when running xfstest 275.  We have been leaking delalloc
metadata space when our reservations fail.  This is because we were improperly
calculating how much space to free for our checksum reservations.  The problem
is we would sometimes free up space that had already been freed in another
thread and we would end up with negative usage for the delalloc space.  This
patch fixes the problem by calculating how much space the other threads would
have already freed, and then calculate how much space we need to free had we not
done the reservation at all, and then freeing any excess space.  This makes
xfstests 275 no longer have leaked space.  Thanks

Reported-by: David Sterba &lt;dsterba@suse.cz&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fusionio.com&gt;
Signed-off-by: Lingzhu Xiang &lt;lxiang@redhat.com&gt;
Reviewed-by: CAI Qian &lt;caiqian@redhat.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>Btrfs: limit the global reserve to 512mb</title>
<updated>2013-04-05T17:04:34Z</updated>
<author>
<name>Josef Bacik</name>
</author>
<published>2013-03-26T19:31:45Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=1c7b6ea87236a0c10943379a6476e2354c133cab'/>
<id>urn:sha1:1c7b6ea87236a0c10943379a6476e2354c133cab</id>
<content type='text'>
commit fdf30d1c1b386e1b73116cc7e0fb14e962b763b0 upstream.

A user reported a problem where he was getting early ENOSPC with hundreds of
gigs of free data space and 6 gigs of free metadata space.  This is because the
global block reserve was taking up the entire free metadata space.  This is
ridiculous, we have infrastructure in place to throttle if we start using too
much of the global reserve, so instead of letting it get this huge just limit it
to 512mb so that users can still get work done.  This allowed the user to
complete his rsync without issues.  Thanks

Reported-and-tested-by: Stefan Priebe &lt;s.priebe@profihost.ag&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fusionio.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>Btrfs: avoid sleeping in verify_parent_transid while atomic</title>
<updated>2012-05-06T11:23:47Z</updated>
<author>
<name>Chris Mason</name>
</author>
<published>2012-05-06T11:23:47Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=b9fab919b748c7b39c19ff236ed6c5682c266dde'/>
<id>urn:sha1:b9fab919b748c7b39c19ff236ed6c5682c266dde</id>
<content type='text'>
verify_parent_transid needs to lock the extent range to make
sure no IO is underway, and so it can safely clear the
uptodate bits if our checks fail.

But, a few callers are using it with spinlocks held.  Most
of the time, the generation numbers are going to match, and
we don't want to switch to a blocking lock just for the error
case.  This adds an atomic flag to verify_parent_transid,
and changes it to return EAGAIN if it needs to block to
properly verifiy things.

Signed-off-by: Chris Mason &lt;chris.mason@oracle.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix block_rsv and space_info lock ordering</title>
<updated>2012-04-27T17:55:14Z</updated>
<author>
<name>Stefan Behrens</name>
</author>
<published>2012-04-27T16:41:46Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=1f699d38b6556c393ac80f1c23c2053502a51631'/>
<id>urn:sha1:1f699d38b6556c393ac80f1c23c2053502a51631</id>
<content type='text'>
may_commit_transaction() calls
        spin_lock(&amp;space_info-&gt;lock);
        spin_lock(&amp;delayed_rsv-&gt;lock);
and update_global_block_rsv() calls
        spin_lock(&amp;block_rsv-&gt;lock);
        spin_lock(&amp;sinfo-&gt;lock);

Lockdep complains about this at run time.
Everywhere except in update_global_block_rsv(), the space_info lock is
the outer lock, therefore the locking order in update_global_block_rsv()
is changed.

Signed-off-by: Stefan Behrens &lt;sbehrens@giantdisaster.de&gt;
Signed-off-by: Chris Mason &lt;chris.mason@oracle.com&gt;
</content>
</entry>
<entry>
<title>btrfs: don't return EINTR</title>
<updated>2012-04-18T17:22:33Z</updated>
<author>
<name>Arne Jansen</name>
</author>
<published>2012-04-18T08:27:16Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=b9688bb8459b67e42327de6420edb405a9188775'/>
<id>urn:sha1:b9688bb8459b67e42327de6420edb405a9188775</id>
<content type='text'>
It is basically a good thing if we are interruptible when waiting for
free space, but the generality in which it is implemented currently
leads to system calls being interruptible that are not documented this
way. For example git can't handle interrupted unlink(), leading to
corrupt repos under space pressure.
Instead we raise the bar to only be interruptible by SIGKILL.
Thanks to David Sterba for suggesting this.

Signed-off-by: Arne Jansen &lt;sensille@gmx.net&gt;
</content>
</entry>
</feed>
