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 Results: Kernel oops, screen freezes.
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 https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1496438/comments/2
I've debugged this a bit, the failure occurs on an atomic_inc on root, when root is NULL, cf: atomic_inc(&root->log_batch);
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
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;
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); does. However, I'm not well at all well versed in btrfs, so I am not confident this is a actually correct. Any comments?
Fixed by de17e793b104d690e1d "btrfs: fix crash/invalid memory access on fsync when using overlayfs", in 4.6.