Bug 101951 - Overlayfs on top of btrfs causes kernel oops + freeze
Summary: Overlayfs on top of btrfs causes kernel oops + freeze
Alias: None
Product: File System
Classification: Unclassified
Component: btrfs (show other bugs)
Hardware: x86-64 Linux
: P1 normal
Assignee: David Sterba
Depends on:
Reported: 2015-07-25 23:17 UTC by Francesco Frassinelli
Modified: 2024-05-09 11:07 UTC (History)
8 users (show)

See Also:
Kernel Version: 4.2.0-0.rc2.git2
Regression: No
Bisected commit-id:

kernel oops log (3.89 KB, text/plain)
2015-07-25 23:17 UTC, Francesco Frassinelli

Description Francesco Frassinelli 2015-07-25 23:17:23 UTC
Created attachment 183641 [details]
kernel oops log

How to reproduce:
$ mkdir {lower,upper,work,overlay}
$ uname > lower/uname
# mount overlay -t overlay -o lowerdir=lower,upperdir=upper,workdir=work overlay
$ # edit overlay/uname

Kernel oops, screen freezes.
Comment 1 Gabriel Rauter 2015-09-17 15:22:21 UTC
I have the same problem although i am using overlay while being in a docker container. Host fs is btrfs on arch linux kernel 4.2.0, guest docker image ubuntu:wily.
kernel oops log can be found here
Comment 2 Colin Ian King 2016-02-10 16:51:25 UTC
I've debugged this a bit, the failure occurs on an atomic_inc on root, when root is NULL, cf:

Comment 3 Colin Ian King 2016-02-16 11:01:18 UTC
bisected: 4bacc9c9234c7c8eec44f5ed4e960d9f96fa0f01 is the first bad commit

commit 4bacc9c9234c7c8eec44f5ed4e960d9f96fa0f01
Author: David Howells <dhowells@redhat.com>
Date: Thu Jun 18 14:32:31 2015 +0100

    overlayfs: Make f_path always point to the overlay and f_inode to the underlay
Comment 4 Colin Ian King 2016-02-16 15:24:24 UTC
The following stops the issue. I'm not sure if it is the correct fix though.

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 098bb8f..5e5df8b 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1884,7 +1884,7 @@ static int start_ordered_ops(struct inode *inode, loff_t start, loff_t end)
 int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = d_inode(dentry);
+       struct inode *inode = file_inode(file);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_trans_handle *trans;
        struct btrfs_log_ctx ctx;
Comment 5 Colin Ian King 2016-02-16 15:41:10 UTC
Commit 4bacc9c9234c7c8eec44f5ed4e960d9f96fa0f01 ("overlayfs: Make f_path
always point to the overlay and f_inode to the underlay") resulted in an
issue when using a combination of btrfs and overlayfs.  This is
noticeable when doing a fsync() on a file in a chroot with overlayfs on
top of btrfs; we hit a kernel oops in btrfs_sync_file() on
atomic_inc(&root->log_batch) because root is NULL.

I've debugged this further and found that in btrfs_sync_file():

	struct inode *inode = d_inode(dentry);

does not return the inode I expected when using the stacked overlay fs,
where as:

	struct inode *inode = file_inode(file);


However, I'm not well at all well versed in btrfs, so I am not confident
this is a actually correct.  Any comments?
Comment 6 David Sterba 2019-05-21 12:33:42 UTC
Fixed by de17e793b104d690e1d "btrfs: fix crash/invalid memory access on fsync when using overlayfs", in 4.6.

Note You need to log in before you can comment on or make changes to this bug.