mirror of
				https://github.com/vyos/vyos-build.git
				synced 2025-10-01 20:28:40 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			297 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 77ce1f672326050d6b47dbab4f52f0bbcd553a37 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 | 110 ++++++++++++++++++++++++++++++-
 | |
|  fs/overlayfs/super.c             |  24 ++++++-
 | |
|  include/linux/inotify.h          |  28 ++++++++
 | |
|  4 files changed, 168 insertions(+), 3 deletions(-)
 | |
| 
 | |
| diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig
 | |
| index 6736e47d94d8..84d9b31300c0 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 b949b2c02f4b..5bbb53db64a4 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 */
 | |
| @@ -75,6 +76,92 @@ struct ctl_table inotify_table[] = {
 | |
|  };
 | |
|  #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;
 | |
| @@ -332,7 +419,7 @@ 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,
 | |
| +static inline int __inotify_find_inode(const char __user *dirname, struct path *path,
 | |
|  						unsigned int flags, __u64 mask)
 | |
|  {
 | |
|  	int error;
 | |
| @@ -354,6 +441,27 @@ 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 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 f5cf0938f298..c3bb42c9d291 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 "overlayfs.h"
 | |
|  
 | |
|  MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
 | |
| @@ -1767,6 +1768,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;
 | |
| @@ -1781,13 +1794,21 @@ static int __init ovl_init(void)
 | |
|  
 | |
|  	err = register_filesystem(&ovl_fs_type);
 | |
|  	if (err)
 | |
| -		kmem_cache_destroy(ovl_inode_cachep);
 | |
| +		goto err;
 | |
| +	err = inotify_register_stackfs(&ovl_inotify);
 | |
| +	if (err)
 | |
| +		goto err;
 | |
| +	return err;
 | |
|  
 | |
| +err:
 | |
| +	kmem_cache_destroy(ovl_inode_cachep);
 | |
| +	unregister_filesystem(&ovl_fs_type);
 | |
|  	return err;
 | |
|  }
 | |
|  
 | |
|  static void __exit ovl_exit(void)
 | |
|  {
 | |
| +	inotify_unregister_stackfs(&ovl_inotify);
 | |
|  	unregister_filesystem(&ovl_fs_type);
 | |
|  
 | |
|  	/*
 | |
| @@ -1796,7 +1817,6 @@ static void __exit ovl_exit(void)
 | |
|  	 */
 | |
|  	rcu_barrier();
 | |
|  	kmem_cache_destroy(ovl_inode_cachep);
 | |
| -
 | |
|  }
 | |
|  
 | |
|  module_init(ovl_init);
 | |
| diff --git a/include/linux/inotify.h b/include/linux/inotify.h
 | |
| index 6a24905f6e1e..4484f0760588 100644
 | |
| --- a/include/linux/inotify.h
 | |
| +++ b/include/linux/inotify.h
 | |
| @@ -9,6 +9,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 */
 | |
|  
 | |
| @@ -20,4 +22,30 @@ extern struct ctl_table inotify_table[]; /* for sysctl */
 | |
|  			  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.2
 | |
| 
 |