<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/git/stable/linux.git/fs/btrfs/inode-map.c, branch linux-3.2.y</title>
<subtitle>Linux kernel stable tree</subtitle>
<id>https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=linux-3.2.y</id>
<link rel='self' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=linux-3.2.y'/>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/'/>
<updated>2015-08-12T14:33:18+00:00</updated>
<entry>
<title>Btrfs: fix race between caching kthread and returning inode to inode cache</title>
<updated>2015-08-12T14:33:18+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2015-06-13T05:52:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=3e05b16a56a9ffc6cd01d155c8599df7d17a8893'/>
<id>urn:sha1:3e05b16a56a9ffc6cd01d155c8599df7d17a8893</id>
<content type='text'>
commit ae9d8f17118551bedd797406a6768b87c2146234 upstream.

While the inode cache caching kthread is calling btrfs_unpin_free_ino(),
we could have a concurrent call to btrfs_return_ino() that adds a new
entry to the root's free space cache of pinned inodes. This concurrent
call does not acquire the fs_info-&gt;commit_root_sem before adding a new
entry if the caching state is BTRFS_CACHE_FINISHED, which is a problem
because the caching kthread calls btrfs_unpin_free_ino() after setting
the caching state to BTRFS_CACHE_FINISHED and therefore races with
the task calling btrfs_return_ino(), which is adding a new entry, while
the former (caching kthread) is navigating the cache's rbtree, removing
and freeing nodes from the cache's rbtree without acquiring the spinlock
that protects the rbtree.

This race resulted in memory corruption due to double free of struct
btrfs_free_space objects because both tasks can end up doing freeing the
same objects. Note that adding a new entry can result in merging it with
other entries in the cache, in which case those entries are freed.
This is particularly important as btrfs_free_space structures are also
used for the block group free space caches.

This memory corruption can be detected by a debugging kernel, which
reports it with the following trace:

[132408.501148] slab error in verify_redzone_free(): cache `btrfs_free_space': double free detected
[132408.505075] CPU: 15 PID: 12248 Comm: btrfs-ino-cache Tainted: G        W       4.1.0-rc5-btrfs-next-10+ #1
[132408.505075] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.1-0-g4adadbd-20150316_085822-nilsson.home.kraxel.org 04/01/2014
[132408.505075]  ffff880023e7d320 ffff880163d73cd8 ffffffff8145eec7 ffffffff81095dce
[132408.505075]  ffff880009735d40 ffff880163d73ce8 ffffffff81154e1e ffff880163d73d68
[132408.505075]  ffffffff81155733 ffffffffa054a95a ffff8801b6099f00 ffffffffa0505b5f
[132408.505075] Call Trace:
[132408.505075]  [&lt;ffffffff8145eec7&gt;] dump_stack+0x4f/0x7b
[132408.505075]  [&lt;ffffffff81095dce&gt;] ? console_unlock+0x356/0x3a2
[132408.505075]  [&lt;ffffffff81154e1e&gt;] __slab_error.isra.28+0x25/0x36
[132408.505075]  [&lt;ffffffff81155733&gt;] __cache_free+0xe2/0x4b6
[132408.505075]  [&lt;ffffffffa054a95a&gt;] ? __btrfs_add_free_space+0x2f0/0x343 [btrfs]
[132408.505075]  [&lt;ffffffffa0505b5f&gt;] ? btrfs_unpin_free_ino+0x8e/0x99 [btrfs]
[132408.505075]  [&lt;ffffffff810f3b30&gt;] ? time_hardirqs_off+0x15/0x28
[132408.505075]  [&lt;ffffffff81084d42&gt;] ? trace_hardirqs_off+0xd/0xf
[132408.505075]  [&lt;ffffffff811563a1&gt;] ? kfree+0xb6/0x14e
[132408.505075]  [&lt;ffffffff811563d0&gt;] kfree+0xe5/0x14e
[132408.505075]  [&lt;ffffffffa0505b5f&gt;] btrfs_unpin_free_ino+0x8e/0x99 [btrfs]
[132408.505075]  [&lt;ffffffffa0505e08&gt;] caching_kthread+0x29e/0x2d9 [btrfs]
[132408.505075]  [&lt;ffffffffa0505b6a&gt;] ? btrfs_unpin_free_ino+0x99/0x99 [btrfs]
[132408.505075]  [&lt;ffffffff8106698f&gt;] kthread+0xef/0xf7
[132408.505075]  [&lt;ffffffff810f3b08&gt;] ? time_hardirqs_on+0x15/0x28
[132408.505075]  [&lt;ffffffff810668a0&gt;] ? __kthread_parkme+0xad/0xad
[132408.505075]  [&lt;ffffffff814653d2&gt;] ret_from_fork+0x42/0x70
[132408.505075]  [&lt;ffffffff810668a0&gt;] ? __kthread_parkme+0xad/0xad
[132408.505075] ffff880023e7d320: redzone 1:0x9f911029d74e35b, redzone 2:0x9f911029d74e35b.
[132409.501654] slab: double free detected in cache 'btrfs_free_space', objp ffff880023e7d320
[132409.503355] ------------[ cut here ]------------
[132409.504241] kernel BUG at mm/slab.c:2571!

Therefore fix this by having btrfs_unpin_free_ino() acquire the lock
that protects the rbtree while doing the searches and removing entries.

Fixes: 1c70d8fb4dfa ("Btrfs: fix inode caching vs tree log")
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings &lt;ben@decadent.org.uk&gt;
</content>
</entry>
<entry>
<title>Btrfs: use kmem_cache_free when freeing entry in inode cache</title>
<updated>2015-08-12T14:33:18+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2015-06-13T05:52:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c6bbfa525c51fd10970b7cb0ed295c5e7ee27511'/>
<id>urn:sha1:c6bbfa525c51fd10970b7cb0ed295c5e7ee27511</id>
<content type='text'>
commit c3f4a1685bb87e59c886ee68f7967eae07d4dffa upstream.

The free space entries are allocated using kmem_cache_zalloc(),
through __btrfs_add_free_space(), therefore we should use
kmem_cache_free() and not kfree() to avoid any confusion and
any potential problem. Looking at the kfree() definition at
mm/slab.c it has the following comment:

  /*
   * (...)
   *
   * Don't free memory not originally allocated by kmalloc()
   * or you will run into trouble.
   */

So better be safe and use kmem_cache_free().

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.cz&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
Signed-off-by: Ben Hutchings &lt;ben@decadent.org.uk&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix inode caching vs tree log</title>
<updated>2014-05-18T13:58:07+00:00</updated>
<author>
<name>Miao Xie</name>
<email>miaox@cn.fujitsu.com</email>
</author>
<published>2014-04-23T11:33:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=d6db8ad79435e2bf42e446cc13ad135dd5ca1f71'/>
<id>urn:sha1:d6db8ad79435e2bf42e446cc13ad135dd5ca1f71</id>
<content type='text'>
commit 1c70d8fb4dfa95bee491816b2a6767b5ca1080e7 upstream.

Currently, with inode cache enabled, we will reuse its inode id immediately
after unlinking file, we may hit something like following:

|-&gt;iput inode
|-&gt;return inode id into inode cache
|-&gt;create dir,fsync
|-&gt;power off

An easy way to reproduce this problem is:

mkfs.btrfs -f /dev/sdb
mount /dev/sdb /mnt -o inode_cache,commit=100
dd if=/dev/zero of=/mnt/data bs=1M count=10 oflag=sync
inode_id=`ls -i /mnt/data | awk '{print $1}'`
rm -f /mnt/data

i=1
while [ 1 ]
do
        mkdir /mnt/dir_$i
        test1=`stat /mnt/dir_$i | grep Inode: | awk '{print $4}'`
        if [ $test1 -eq $inode_id ]
        then
		dd if=/dev/zero of=/mnt/dir_$i/data bs=1M count=1 oflag=sync
		echo b &gt; /proc/sysrq-trigger
	fi
	sleep 1
        i=$(($i+1))
done

mount /dev/sdb /mnt
umount /dev/sdb
btrfs check /dev/sdb

We fix this problem by adding unlinked inode's id into pinned tree,
and we can not reuse them until committing transaction.

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Wang Shilong &lt;wangsl.fnst@cn.fujitsu.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings &lt;ben@decadent.org.uk&gt;
</content>
</entry>
<entry>
<title>Btrfs: Don't allocate inode that is already in use</title>
<updated>2014-05-18T13:58:07+00:00</updated>
<author>
<name>Stefan Behrens</name>
<email>sbehrens@giantdisaster.de</email>
</author>
<published>2013-10-15T18:08:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=8bbfb31d6b0eef58364978299a90bb37dc8e01f0'/>
<id>urn:sha1:8bbfb31d6b0eef58364978299a90bb37dc8e01f0</id>
<content type='text'>
commit ff76b0565523319d7c1c0b51d5a5a8915d33efab upstream.

Due to an off-by-one error, it is possible to reproduce a bug
when the inode cache is used.

The same inode number is assigned twice, the second time this
leads to an EEXIST in btrfs_insert_empty_items().

The issue can happen when a file is removed right after a subvolume
is created and then a new inode number is created before the
inodes in free_inode_pinned are processed.
unlink() calls btrfs_return_ino() which calls start_caching() in this
case which adds [highest_ino + 1, BTRFS_LAST_FREE_OBJECTID] by
searching for the highest inode (which already cannot find the
unlinked one anymore in btrfs_find_free_objectid()). So if this
unlinked inode's number is equal to the highest_ino + 1 (or &gt;= this value
instead of &gt; this value which was the off-by-one error), we mustn't add
the inode number to free_ino_pinned (caching_thread() does it right).
In this case we need to try directly to add the number to the inode_cache
which will fail in this case.

When this inode number is allocated while it is still in free_ino_pinned,
it is allocated and still added to the free inode cache when the
pinned inodes are processed, thus one of the following inode number
allocations will get an inode that is already in use and fail with EEXIST
in btrfs_insert_empty_items().

One example which was created with the reproducer below:
Create a snapshot, work in the newly created snapshot for the rest.
In unlink(inode 34284) call btrfs_return_ino() which calls start_caching().
start_caching() calls add_free_space [34284, 18446744073709517077].
In btrfs_return_ino(), call start_caching pinned [34284, 1] which is wrong.
mkdir() call btrfs_find_ino_for_alloc() which returns the number 34284.
btrfs_unpin_free_ino calls add_free_space [34284, 1].
mkdir() call btrfs_find_ino_for_alloc() which returns the number 34284.
EEXIST when the new inode is inserted.

One possible reproducer is this one:
 #!/bin/sh
 # preparation
TEST_DEV=/dev/sdc1
TEST_MNT=/mnt
umount ${TEST_MNT} 2&gt;/dev/null || true
mkfs.btrfs -f ${TEST_DEV}
mount ${TEST_DEV} ${TEST_MNT} -o \
 rw,relatime,compress=lzo,space_cache,inode_cache
btrfs subv create ${TEST_MNT}/s1
for i in `seq 34027`; do touch ${TEST_MNT}/s1/${i}; done
btrfs subv snap ${TEST_MNT}/s1 ${TEST_MNT}/s2
FILENAME=`find ${TEST_MNT}/s1/ -inum 4085 | sed 's|^.*/\([^/]*\)$|\1|'`
rm ${TEST_MNT}/s2/$FILENAME
touch ${TEST_MNT}/s2/$FILENAME
 # the following steps can be repeated to reproduce the issue again and again
[ -e ${TEST_MNT}/s3 ] &amp;&amp; btrfs subv del ${TEST_MNT}/s3
btrfs subv snap ${TEST_MNT}/s2 ${TEST_MNT}/s3
rm ${TEST_MNT}/s3/$FILENAME
touch ${TEST_MNT}/s3/$FILENAME
ls -alFi ${TEST_MNT}/s?/$FILENAME
touch ${TEST_MNT}/s3/_1 || logger FAILED
ls -alFi ${TEST_MNT}/s?/_1
touch ${TEST_MNT}/s3/_2 || logger FAILED
ls -alFi ${TEST_MNT}/s?/_2
touch ${TEST_MNT}/s3/__1 || logger FAILED
ls -alFi ${TEST_MNT}/s?/__1
touch ${TEST_MNT}/s3/__2 || logger FAILED
ls -alFi ${TEST_MNT}/s?/__2
 # if the above is not enough, add the following loop:
for i in `seq 3 9`; do touch ${TEST_MNT}/s3/__${i} || logger FAILED; done
 #for i in `seq 3 34027`; do touch ${TEST_MNT}/s3/__${i} || logger FAILED; done
 # one of the touch(1) calls in s3 fail due to EEXIST because the inode is
 # already in use that btrfs_find_ino_for_alloc() returns.

Signed-off-by: Stefan Behrens &lt;sbehrens@giantdisaster.de&gt;
Reviewed-by: Jan Schmidt &lt;list.btrfs@jan-o-sch.net&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fusionio.com&gt;
Signed-off-by: Chris Mason &lt;chris.mason@fusionio.com&gt;
Signed-off-by: Ben Hutchings &lt;ben@decadent.org.uk&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix no reserved space for writing out inode cache</title>
<updated>2011-11-11T01:45:04+00:00</updated>
<author>
<name>Miao Xie</name>
<email>miaox@cn.fujitsu.com</email>
</author>
<published>2011-11-11T01:45:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=ba38eb4de354d228f2792f93cde2c748a3a3f3b2'/>
<id>urn:sha1:ba38eb4de354d228f2792f93cde2c748a3a3f3b2</id>
<content type='text'>
I-node cache forgets to reserve the space when writing out it. And when
we do some stress test, such as synctest, it will trigger WARN_ON() in
use_block_rsv().

WARNING: at fs/btrfs/extent-tree.c:5718 btrfs_alloc_free_block+0xbf/0x281 [btrfs]()
...
Call Trace:
 [&lt;ffffffff8104df86&gt;] warn_slowpath_common+0x80/0x98
 [&lt;ffffffff8104dfb3&gt;] warn_slowpath_null+0x15/0x17
 [&lt;ffffffffa0369c60&gt;] btrfs_alloc_free_block+0xbf/0x281 [btrfs]
 [&lt;ffffffff810cbcb8&gt;] ? __set_page_dirty_nobuffers+0xfe/0x108
 [&lt;ffffffffa035c040&gt;] __btrfs_cow_block+0x118/0x3b5 [btrfs]
 [&lt;ffffffffa035c7ba&gt;] btrfs_cow_block+0x103/0x14e [btrfs]
 [&lt;ffffffffa035e4c4&gt;] btrfs_search_slot+0x249/0x6a4 [btrfs]
 [&lt;ffffffffa036d086&gt;] btrfs_lookup_inode+0x2a/0x8a [btrfs]
 [&lt;ffffffffa03788b7&gt;] btrfs_update_inode+0xaa/0x141 [btrfs]
 [&lt;ffffffffa036d7ec&gt;] btrfs_save_ino_cache+0xea/0x202 [btrfs]
 [&lt;ffffffffa03a761e&gt;] ? btrfs_update_reloc_root+0x17e/0x197 [btrfs]
 [&lt;ffffffffa0373867&gt;] commit_fs_roots+0xaa/0x158 [btrfs]
 [&lt;ffffffffa03746a6&gt;] btrfs_commit_transaction+0x405/0x731 [btrfs]
 [&lt;ffffffff810690df&gt;] ? wake_up_bit+0x25/0x25
 [&lt;ffffffffa039d652&gt;] ? btrfs_log_dentry_safe+0x43/0x51 [btrfs]
 [&lt;ffffffffa0381c5f&gt;] btrfs_sync_file+0x16a/0x198 [btrfs]
 [&lt;ffffffff81122806&gt;] ? mntput+0x21/0x23
 [&lt;ffffffff8112d150&gt;] vfs_fsync_range+0x18/0x21
 [&lt;ffffffff8112d170&gt;] vfs_fsync+0x17/0x19
 [&lt;ffffffff8112d316&gt;] do_fsync+0x29/0x3e
 [&lt;ffffffff8112d348&gt;] sys_fsync+0xb/0xf
 [&lt;ffffffff81468352&gt;] system_call_fastpath+0x16/0x1b

Sometimes it causes BUG_ON() in the reservation code of the delayed inode
is triggered.

So we must reserve enough space for inode cache.

Note: If we can not reserve the enough space for inode cache, we will
give up writing out it.

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Chris Mason &lt;chris.mason@oracle.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: handle enospc accounting for free space inodes</title>
<updated>2011-10-19T19:12:42+00:00</updated>
<author>
<name>Josef Bacik</name>
<email>josef@redhat.com</email>
</author>
<published>2011-08-30T14:19:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c09544e07f8cdc455ed8615d4c067d694c33bd18'/>
<id>urn:sha1:c09544e07f8cdc455ed8615d4c067d694c33bd18</id>
<content type='text'>
Since free space inodes now use normal checksumming we need to make sure to
account for their metadata use.  So reserve metadata space, and then if we fail
to write out the metadata we can just release it, otherwise it will be freed up
when the io completes.  Thanks,

Signed-off-by: Josef Bacik &lt;josef@redhat.com&gt;
</content>
</entry>
<entry>
<title>btrfs: add helper for fs_info-&gt;closing</title>
<updated>2011-06-04T12:11:22+00:00</updated>
<author>
<name>David Sterba</name>
<email>dsterba@suse.cz</email>
</author>
<published>2011-05-31T16:07:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7841cb2898f66a73062c64d0ef5733dde7279e46'/>
<id>urn:sha1:7841cb2898f66a73062c64d0ef5733dde7279e46</id>
<content type='text'>
wrap checking of filesystem 'closing' flag and fix a few missing memory
barriers.

Signed-off-by: David Sterba &lt;dsterba@suse.cz&gt;
</content>
</entry>
<entry>
<title>Btrfs: add mount -o inode_cache</title>
<updated>2011-06-04T12:03:47+00:00</updated>
<author>
<name>Chris Mason</name>
<email>chris.mason@oracle.com</email>
</author>
<published>2011-06-03T13:36:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=4b9465cb9e3859186eefa1ca3b990a5849386320'/>
<id>urn:sha1:4b9465cb9e3859186eefa1ca3b990a5849386320</id>
<content type='text'>
This makes the inode map cache default to off until we
fix the overflow problem when the free space crcs don't fit
inside a single page.

Signed-off-by: Chris Mason &lt;chris.mason@oracle.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: don't save the inode cache if we are deleting this root</title>
<updated>2011-06-04T12:03:45+00:00</updated>
<author>
<name>Josef Bacik</name>
<email>josef@redhat.com</email>
</author>
<published>2011-05-31T19:33:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=d132a538d258f8f52fd0cd8b5017755f4e915386'/>
<id>urn:sha1:d132a538d258f8f52fd0cd8b5017755f4e915386</id>
<content type='text'>
With xfstest 254 I can panic the box every time with the inode number caching
stuff on.  This is because we clean the inodes out when we delete the subvolume,
but then we write out the inode cache which adds an inode to the subvolume inode
tree, and then when it gets evicted again the root gets added back on the dead
roots list and is deleted again, so we have a double free.  To stop this from
happening just return 0 if refs is 0 (and we're not the tree root since tree
root always has refs of 0).  With this fix 254 no longer panics.  Thanks,

Signed-off-by: Josef Bacik &lt;josef@redhat.com&gt;
Tested-by: David Sterba &lt;dsterba@suse.cz&gt;
Signed-off-by: Chris Mason &lt;chris.mason@oracle.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: don't save the inode cache in non-FS roots</title>
<updated>2011-06-04T12:03:44+00:00</updated>
<author>
<name>liubo</name>
<email>liubo2009@cn.fujitsu.com</email>
</author>
<published>2011-06-01T09:42:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=ca456ae280c0646e1e571c3b9a3834c55e90adfe'/>
<id>urn:sha1:ca456ae280c0646e1e571c3b9a3834c55e90adfe</id>
<content type='text'>
This adds extra checks to make sure the inode map we are caching really
belongs to a FS root instead of a special relocation tree.  It
prevents crashes during balancing operations.

Signed-off-by: Liu Bo &lt;liubo2009@cn.fujitsu.com&gt;
Signed-off-by: Chris Mason &lt;chris.mason@oracle.com&gt;
</content>
</entry>
</feed>
