Package: linux-source-4.8 Severity: important Tags: patch When using tail on the liveCD some updates are not reported. This seems to be triggered by tail using inotify to identify modified files. Overlayfs does not appear to be implementing inotify quite the way you might hope reporting only against the underlying filesystems.
^^ This is the description of the original bug filed 2011-10-26 by Andy Whitcroft. (https://bugs.launchpad.net/ubuntu/+source/linux/+bug/882147) It still applies and the bug is still present and still renders live isos unusable to a degree. One could say it's a "non-feature" but i would still call it bug. Unfortunately debian-live-isos are bitten by this too. The applied patch is the basicly the patch in the bugreport and applies to kernel 4.8 - and solve the problem with live isos. Cheers Alf -- System Information: Debian Release: stretch/sid APT prefers buildd-unstable APT policy: (500, 'buildd-unstable'), (500, 'unstable'), (500, 'testing'), (500, 'stable'), (1, 'experimental') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 4.9.2-towo.1-siduction-amd64 (SMP w/8 CPU cores; PREEMPT) Locale: LANG=de_DE.utf8, LC_CTYPE=de_DE.utf8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system)
diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig index b981fc0..1ccd92e 100644 --- a/fs/notify/inotify/Kconfig +++ b/fs/notify/inotify/Kconfig @@ -15,3 +15,12 @@ config INOTIFY_USER For more information, see <file:Documentation/filesystems/inotify.txt> If unsure, say Y. + +config INOTIFY_STACKFS + bool "Inotify support for stackable filesystem" + select INOTIFY_USER + default y + ---help--- + Say Y here to enable inotify support for stackable filesystem. + + If unsure, say N. diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 60f954a..3daff50 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -24,6 +24,7 @@ #include <linux/file.h> #include <linux/fs.h> /* struct inode */ +#include <linux/mount.h> #include <linux/fsnotify_backend.h> #include <linux/idr.h> #include <linux/init.h> /* fs_initcall */ @@ -86,6 +86,94 @@ }; #endif /* CONFIG_SYSCTL */ +#ifdef CONFIG_INOTIFY_STACKFS + +static DEFINE_RWLOCK(inotify_fs_lock); +static LIST_HEAD(inotify_fs_list); + +static inline struct file_system_type* peek_fs_type(struct path *path) +{ + return path->mnt->mnt_sb->s_type; +} + +static struct inotify_stackfs* inotify_get_stackfs(struct path *path) +{ + struct file_system_type *fs; + struct inotify_stackfs *fse, *ret = NULL; + + fs = peek_fs_type(path); + + read_lock(&inotify_fs_lock); + list_for_each_entry(fse, &inotify_fs_list, list) { + if (fse->fs_type == fs) { + ret = fse; + break; + } + } + read_unlock(&inotify_fs_lock); + + return ret; +} + +static inline void inotify_put_stackfs(struct inotify_stackfs *fs) +{ +} + +int inotify_register_stackfs(struct inotify_stackfs *fs) +{ + int ret = 0; + struct inotify_stackfs *fse; + + BUG_ON(IS_ERR_OR_NULL(fs->fs_type)); + BUG_ON(IS_ERR_OR_NULL(fs->func)); + + INIT_LIST_HEAD(&fs->list); + + write_lock(&inotify_fs_lock); + list_for_each_entry(fse, &inotify_fs_list, list) { + if (fse->fs_type == fs->fs_type) { + write_unlock(&inotify_fs_lock); + ret = -EBUSY; + goto out; + } + } + list_add_tail(&fs->list, &inotify_fs_list); + write_unlock(&inotify_fs_lock); + +out: + return ret; +} +EXPORT_SYMBOL_GPL(inotify_register_stackfs); + +void inotify_unregister_stackfs(struct inotify_stackfs *fs) +{ + struct inotify_stackfs *fse, *n; + + write_lock(&inotify_fs_lock); + list_for_each_entry_safe(fse, n, &inotify_fs_list, list) { + if (fse == fs) { + list_del(&fse->list); + break; + } + } + write_unlock(&inotify_fs_lock); +} +EXPORT_SYMBOL_GPL(inotify_unregister_stackfs); + +#else + +static inline struct inotify_stackfs* inotify_get_stackfs(struct path *path) +{ + return NULL; +} + +static inline void inotify_put_stackfs(struct inotify_stackfs *fs) +{ +} + +#endif /* CONFIG_INOTIFY_STACKFS */ + + static inline __u32 inotify_arg_to_mask(u32 arg) { __u32 mask; @@ -329,7 +417,7 @@ /* * find_inode - resolve a user-given path to a specific inode */ -static int inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) +static inline int __inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) { int error; @@ -343,6 +431,27 @@ return error; } +static int inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) +{ + int ret; + struct path tpath; + struct inotify_stackfs *fse; + + ret = __inotify_find_inode(dirname, &tpath, flags); + if (ret) + return ret; + fse = inotify_get_stackfs(&tpath); + if (fse == NULL) { + *path = tpath; + return 0; + } + ret = fse->func(path, &tpath); + inotify_put_stackfs(fse); + path_put(&tpath); + + return ret; +} + static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock, struct inotify_inode_mark *i_mark) { diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 9473e79..4af5048 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -19,6 +19,7 @@ #include <linux/sched.h> #include <linux/statfs.h> #include <linux/seq_file.h> +#include <linux/inotify.h> #include <linux/posix_acl_xattr.h> #include "overlayfs.h" @@ -1395,13 +1396,39 @@ }; MODULE_ALIAS_FS("overlay"); +static int ovl_inotify_path(struct path *dst, struct path *src) +{ + ovl_path_real(src->dentry, dst); + + path_get(dst); + + return 0; +} + +static struct inotify_stackfs ovl_inotify = { + .fs_type = &ovl_fs_type, + .func = ovl_inotify_path, +}; + static int __init ovl_init(void) { - return register_filesystem(&ovl_fs_type); + int ret; + + ret = register_filesystem(&ovl_fs_type); + if (ret) + return ret; + ret = inotify_register_stackfs(&ovl_inotify); + if (ret) { + pr_err("overlayfs: hook inotify error\n"); + unregister_filesystem(&ovl_fs_type); + } + + return ret; } static void __exit ovl_exit(void) { + inotify_unregister_stackfs(&ovl_inotify); unregister_filesystem(&ovl_fs_type); } diff --git a/include/linux/inotify.h b/include/linux/inotify.h index 23aede0..2c4d7a1 100644 --- a/include/linux/inotify.h +++ b/include/linux/inotify.h @@ -8,6 +8,8 @@ #include <linux/sysctl.h> #include <uapi/linux/inotify.h> +#include <linux/list.h> +#include <linux/fs.h> extern struct ctl_table inotify_table[]; /* for sysctl */ @@ -19,4 +21,30 @@ extern struct ctl_table inotify_table[]; /* for sysctl */ IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_MASK_ADD | \ IN_ISDIR | IN_ONESHOT) +typedef int (*inotify_path_proc)(struct path *dst, struct path *src); + +struct inotify_stackfs { + struct list_head list; /* entry in inotify_fs_list */ + struct file_system_type *fs_type; /* registed file_system_type */ + inotify_path_proc func; /* registed callback function */ +}; + +#ifdef CONFIG_INOTIFY_STACKFS + +extern int inotify_register_stackfs(struct inotify_stackfs *fs); +extern void inotify_unregister_stackfs(struct inotify_stackfs *fs); + +#else + +static inline int inotify_register_stackfs(struct inotify_stackfs *fs) +{ + return 0; +} + +static inline void inotify_unregister_stackfs(struct inotify_stackfs *fs) +{ +} + +#endif /* CONFIG_INOTIFY_STACKFS */ + #endif /* _LINUX_INOTIFY_H */