Skip to content

Commit 1c70d8f

Browse files
Miao Xiemasoncl
authored andcommitted
Btrfs: fix inode caching vs tree log
Currently, with inode cache enabled, we will reuse its inode id immediately after unlinking file, we may hit something like following: |->iput inode |->return inode id into inode cache |->create dir,fsync |->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 > /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. Cc: [email protected] Signed-off-by: Miao Xie <[email protected]> Signed-off-by: Wang Shilong <[email protected]> Signed-off-by: Chris Mason <[email protected]>
1 parent 28c16cb commit 1c70d8f

File tree

1 file changed

+2
-16
lines changed

1 file changed

+2
-16
lines changed

fs/btrfs/inode-map.c

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -209,24 +209,14 @@ int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid)
209209

210210
void btrfs_return_ino(struct btrfs_root *root, u64 objectid)
211211
{
212-
struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
213212
struct btrfs_free_space_ctl *pinned = root->free_ino_pinned;
214213

215214
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
216215
return;
217-
218216
again:
219217
if (root->cached == BTRFS_CACHE_FINISHED) {
220-
__btrfs_add_free_space(ctl, objectid, 1);
218+
__btrfs_add_free_space(pinned, objectid, 1);
221219
} else {
222-
/*
223-
* If we are in the process of caching free ino chunks,
224-
* to avoid adding the same inode number to the free_ino
225-
* tree twice due to cross transaction, we'll leave it
226-
* in the pinned tree until a transaction is committed
227-
* or the caching work is done.
228-
*/
229-
230220
down_write(&root->fs_info->commit_root_sem);
231221
spin_lock(&root->cache_lock);
232222
if (root->cached == BTRFS_CACHE_FINISHED) {
@@ -238,11 +228,7 @@ void btrfs_return_ino(struct btrfs_root *root, u64 objectid)
238228

239229
start_caching(root);
240230

241-
if (objectid <= root->cache_progress ||
242-
objectid >= root->highest_objectid)
243-
__btrfs_add_free_space(ctl, objectid, 1);
244-
else
245-
__btrfs_add_free_space(pinned, objectid, 1);
231+
__btrfs_add_free_space(pinned, objectid, 1);
246232

247233
up_write(&root->fs_info->commit_root_sem);
248234
}

0 commit comments

Comments
 (0)