Re: [PATCH 11/11] btrfs: use automount to bind-mount all subvol roots.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jul 28, 2021 at 08:37:45AM +1000, NeilBrown wrote:
> All subvol roots are now marked as automounts.  If the d_automount()
> function determines that the dentry is not the root of the vfsmount, it
> creates a simple loop-back mount of the dentry onto itself.  If it
> determines that it IS the root of the vfsmount, it returns -EISDIR so
> that no further automounting is attempted.
> 
> btrfs_getattr pays special attention to these automount dentries.
> If it is NOT the root of the vfsmount:
>  - the ->dev is reported as that for the rest of the vfsmount
>  - the ->ino is reported as the subvol objectid, suitable transformed
>    to avoid collision.
> 
> This way the same inode appear to be different depending on which mount
> it is in.
> 
> automounted vfsmounts are kept on a list and timeout after 500 to 1000
> seconds of last use.  This is configurable via a module parameter.
> The tracking and timeout of automounts is copied from NFS.
> 
> Link: https://lore.kernel.org/r/162742546558.32498.1901201501617899416.stgit@noble.brown
> Reported-by: kernel test robot <lkp@xxxxxxxxx>
> Signed-off-by: NeilBrown <neilb@xxxxxxx>
> ---
>  fs/btrfs/btrfs_inode.h |    2 +
>  fs/btrfs/inode.c       |  108 ++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/btrfs/super.c       |    1 
>  3 files changed, 111 insertions(+)
> 
> diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
> index a4b5f38196e6..f03056cacc4a 100644
> --- a/fs/btrfs/btrfs_inode.h
> +++ b/fs/btrfs/btrfs_inode.h
> @@ -387,4 +387,6 @@ static inline void btrfs_print_data_csum_error(struct btrfs_inode *inode,
>  			mirror_num);
>  }
>  
> +void btrfs_release_automount_timer(void);
> +
>  #endif
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 02537c1a9763..a5f46545fb38 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -31,6 +31,7 @@
>  #include <linux/migrate.h>
>  #include <linux/sched/mm.h>
>  #include <linux/iomap.h>
> +#include <linux/fs_context.h>
>  #include <asm/unaligned.h>
>  #include "misc.h"
>  #include "ctree.h"
> @@ -5782,6 +5783,8 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p)
>  	struct btrfs_iget_args *args = p;
>  
>  	inode->i_ino = args->ino;
> +	if (args->ino == BTRFS_FIRST_FREE_OBJECTID)
> +		inode->i_flags |= S_AUTOMOUNT;
>  	BTRFS_I(inode)->location.objectid = args->ino;
>  	BTRFS_I(inode)->location.type = BTRFS_INODE_ITEM_KEY;
>  	BTRFS_I(inode)->location.offset = 0;
> @@ -5985,6 +5988,101 @@ static int btrfs_dentry_delete(const struct dentry *dentry)
>  	return 0;
>  }
>  
> +static void btrfs_expire_automounts(struct work_struct *work);
> +static LIST_HEAD(btrfs_automount_list);
> +static DECLARE_DELAYED_WORK(btrfs_automount_task, btrfs_expire_automounts);
> +int btrfs_mountpoint_expiry_timeout = 500 * HZ;
> +static void btrfs_expire_automounts(struct work_struct *work)
> +{
> +	struct list_head *list = &btrfs_automount_list;
> +	int timeout = READ_ONCE(btrfs_mountpoint_expiry_timeout);
> +
> +	mark_mounts_for_expiry(list);
> +	if (!list_empty(list) && timeout > 0)
> +		schedule_delayed_work(&btrfs_automount_task, timeout);
> +}
> +
> +void btrfs_release_automount_timer(void)
> +{
> +	if (list_empty(&btrfs_automount_list))
> +		cancel_delayed_work(&btrfs_automount_task);
> +}
> +
> +static struct vfsmount *btrfs_automount(struct path *path)
> +{
> +	struct fs_context fc;
> +	struct vfsmount *mnt;
> +	int timeout = READ_ONCE(btrfs_mountpoint_expiry_timeout);
> +
> +	if (path->dentry == path->mnt->mnt_root)
> +		/* dentry is root of the vfsmount,
> +		 * so skip automount processing
> +		 */
> +		return ERR_PTR(-EISDIR);
> +	/* Create a bind-mount to expose the subvol in the mount table */
> +	fc.root = path->dentry;
> +	fc.sb_flags = 0;
> +	fc.source = "btrfs-automount";
> +	mnt = vfs_create_mount(&fc);
> +	if (IS_ERR(mnt))
> +		return mnt;

Hey Neil,

Sorry if this is a stupid question but wouldn't you want to copy the
mount properties from path->mnt here? Couldn't you otherwise use this to
e.g. suddenly expose a dentry on a read-only mount as read-write?

Christian



[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux