mirror of
				https://github.com/vyos/vyos-build.git
				synced 2025-10-01 20:28:40 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			300 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			300 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 1d625d2f745b61a718ce52cd1729f467c17defa6 Mon Sep 17 00:00:00 2001
 | |
| From: Alex Harpin <development@landsofshadow.co.uk>
 | |
| Date: Wed, 31 Dec 2014 10:33:38 +0000
 | |
| Subject: [PATCH] VyOS: add inotify support for stackable filesystems
 | |
|  (overlayfs)
 | |
| 
 | |
| As it stands at the moment, overlayfs doesn't have full support for
 | |
| inotify, and as such anything that relies on inotify currently has
 | |
| issues.  The simplest method of demonstrating this is to tail a file
 | |
| (so tail -f /var/log/messages) and see that it doesn't follow changes
 | |
| in that file.  This has been reported in a number of places, including
 | |
| Bug #882147 in Ubuntu.  This patch is based on the version proposed by
 | |
| Li Jianguo in response to this bug, adding support for inotify in
 | |
| stackable filesystems.
 | |
| 
 | |
| This commit provides a complete fix for the workaround implemented
 | |
| for bug #303, and will allow that commit to be reverted.
 | |
| 
 | |
| Bug #425 http://bugzilla.vyos.net/show_bug.cgi?id=425
 | |
| 
 | |
| (cherry picked from commit a93f1128bc83b5a6628da242e71c18ef05e81ea2)
 | |
| 
 | |
| ---
 | |
|  fs/notify/inotify/Kconfig        |   9 +++
 | |
|  fs/notify/inotify/inotify_user.c | 114 ++++++++++++++++++++++++++++++-
 | |
|  fs/overlayfs/super.c             |  27 ++++++--
 | |
|  include/linux/inotify.h          |  28 ++++++++
 | |
|  4 files changed, 172 insertions(+), 6 deletions(-)
 | |
| 
 | |
| diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig
 | |
| index 1cc8be25df7e..bc4acd1a6ea4 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.rst>
 | |
|  
 | |
|  	  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 1c4bfdab008d..cf567cc33679 100644
 | |
| --- a/fs/notify/inotify/inotify_user.c
 | |
| +++ b/fs/notify/inotify/inotify_user.c
 | |
| @@ -15,6 +15,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 */
 | |
| @@ -97,6 +98,93 @@ static void __init inotify_sysctls_init(void)
 | |
|  #define inotify_sysctls_init() do { } while (0)
 | |
|  #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(struct inode *inode, u32 arg)
 | |
|  {
 | |
|  	__u32 mask;
 | |
| @@ -370,8 +458,8 @@ static const struct file_operations inotify_fops = {
 | |
|  /*
 | |
|   * find_inode - resolve a user-given path to a specific inode
 | |
|   */
 | |
| -static int inotify_find_inode(const char __user *dirname, struct path *path,
 | |
| -						unsigned int flags, __u64 mask)
 | |
| +static inline int __inotify_find_inode(const char __user *dirname, struct path *path,
 | |
| +					unsigned int flags, __u64 mask)
 | |
|  {
 | |
|  	int error;
 | |
|  
 | |
| @@ -392,6 +480,28 @@ static int inotify_find_inode(const char __user *dirname, struct path *path,
 | |
|  	return error;
 | |
|  }
 | |
|  
 | |
| +static int inotify_find_inode(const char __user *dirname, struct path *path,
 | |
| +					unsigned int flags, __u64 mask)
 | |
| +{
 | |
| +	int ret;
 | |
| +	struct path tpath;
 | |
| +	struct inotify_stackfs *fse;
 | |
| +
 | |
| +	ret = __inotify_find_inode(dirname, &tpath, flags, mask);
 | |
| +	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 93ee57bc82ad..5f4f886d011e 100644
 | |
| --- a/fs/overlayfs/super.c
 | |
| +++ b/fs/overlayfs/super.c
 | |
| @@ -15,6 +15,7 @@
 | |
|  #include <linux/seq_file.h>
 | |
|  #include <linux/posix_acl_xattr.h>
 | |
|  #include <linux/exportfs.h>
 | |
| +#include <linux/inotify.h>
 | |
|  #include <linux/file.h>
 | |
|  #include <linux/fs_context.h>
 | |
|  #include <linux/fs_parser.h>
 | |
| @@ -1533,6 +1534,18 @@ static void ovl_inode_init_once(void *foo)
 | |
|  	inode_init_once(&oi->vfs_inode);
 | |
|  }
 | |
|  
 | |
| +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)
 | |
|  {
 | |
|  	int err;
 | |
| @@ -1548,18 +1561,24 @@ static int __init ovl_init(void)
 | |
|  	err = ovl_aio_request_cache_init();
 | |
|  	if (!err) {
 | |
|  		err = register_filesystem(&ovl_fs_type);
 | |
| -		if (!err)
 | |
| -			return 0;
 | |
| +		if (err)
 | |
| +			goto err;
 | |
| +		err = inotify_register_stackfs(&ovl_inotify);
 | |
| +		if (err)
 | |
| +			goto err;
 | |
| +		return 0;
 | |
|  
 | |
| -		ovl_aio_request_cache_destroy();
 | |
|  	}
 | |
| +err:
 | |
|  	kmem_cache_destroy(ovl_inode_cachep);
 | |
| -
 | |
| +	unregister_filesystem(&ovl_fs_type);
 | |
| +	ovl_aio_request_cache_destroy();
 | |
|  	return err;
 | |
|  }
 | |
|  
 | |
|  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 8d20caa1b268..c126e2f93a73 100644
 | |
| --- a/include/linux/inotify.h
 | |
| +++ b/include/linux/inotify.h
 | |
| @@ -8,6 +8,8 @@
 | |
|  #define _LINUX_INOTIFY_H
 | |
|  
 | |
|  #include <uapi/linux/inotify.h>
 | |
| +#include <linux/list.h>
 | |
| +#include <linux/fs.h>
 | |
|  
 | |
|  #define ALL_INOTIFY_BITS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
 | |
|  			  IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
 | |
| @@ -17,4 +19,30 @@
 | |
|  			  IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_MASK_ADD | \
 | |
|  			  IN_MASK_CREATE | 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 */
 | |
| -- 
 | |
| 2.39.5
 | |
| 
 |