Commit 9512a2c3 authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: loopback-mounted branch



It is ok that the branch is loopback-mounted.
But it had a problem if the backend fs-image is placed on another
branch, and aufs had prohibited such nested branch for a long time due
to the recursive lookup by 'loopN' daemon.
I don't remember when it was, but the daemon stopped such recursive
behaviour, but aufs is still prohibitting the nested branch via
loopback-mount.
Upon the request from users, aufs will allow the loopback-mounted branch
on another branch by another patch (aufs4-loopback.patch in
aufs4-standalone.git).
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 3be35a97
...@@ -138,6 +138,14 @@ config AUFS_SHWH ...@@ -138,6 +138,14 @@ config AUFS_SHWH
sounds like philosophy or something, but in technically it sounds like philosophy or something, but in technically it
simply shows the name of whiteout with keeping its behaviour. simply shows the name of whiteout with keeping its behaviour.
config AUFS_BDEV_LOOP
bool
depends on BLK_DEV_LOOP
default y
help
Automatic configuration for internal use.
Convert =[ym] into =y.
config AUFS_DEBUG config AUFS_DEBUG
bool "Debug aufs" bool "Debug aufs"
help help
......
...@@ -24,6 +24,7 @@ aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \ ...@@ -24,6 +24,7 @@ aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
aufs-$(CONFIG_PROC_FS) += procfs.o plink.o aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
aufs-$(CONFIG_SYSFS) += sysfs.o aufs-$(CONFIG_SYSFS) += sysfs.o
aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
aufs-$(CONFIG_AUFS_EXPORT) += export.o aufs-$(CONFIG_AUFS_EXPORT) += export.o
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "hbl.h" #include "hbl.h"
#include "inode.h" #include "inode.h"
#include "lcnt.h" #include "lcnt.h"
#include "loop.h"
#include "module.h" #include "module.h"
#include "opts.h" #include "opts.h"
#include "rwsem.h" #include "rwsem.h"
......
...@@ -102,7 +102,8 @@ int au_br_index(struct super_block *sb, aufs_bindex_t br_id) ...@@ -102,7 +102,8 @@ int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
static int test_overlap(struct super_block *sb, struct dentry *h_adding, static int test_overlap(struct super_block *sb, struct dentry *h_adding,
struct dentry *h_root) struct dentry *h_root)
{ {
if (unlikely(h_adding == h_root)) if (unlikely(h_adding == h_root
|| au_test_loopback_overlap(sb, h_adding)))
return 1; return 1;
if (h_adding->d_sb != h_root->d_sb) if (h_adding->d_sb != h_root->d_sb)
return 0; return 0;
......
...@@ -345,6 +345,13 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) ...@@ -345,6 +345,13 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
if (IS_ERR(h_file)) if (IS_ERR(h_file))
goto out; goto out;
if (au_test_loopback_kthread()) {
au_warn_loopback(h_file->f_path.dentry->d_sb);
if (file->f_mapping != h_file->f_mapping) {
file->f_mapping = h_file->f_mapping;
smp_mb(); /* unnecessary? */
}
}
fi_read_unlock(file); fi_read_unlock(file);
err = au_do_iter(h_file, MAY_READ, kio, iov_iter); err = au_do_iter(h_file, MAY_READ, kio, iov_iter);
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2005-2019 Junjiro R. Okajima
*/
/*
* support for loopback block device as a branch
*/
#include "aufs.h"
/* added into drivers/block/loop.c */
static struct file *(*backing_file_func)(struct super_block *sb);
/*
* test if two lower dentries have overlapping branches.
*/
int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
{
struct super_block *h_sb;
struct file *backing_file;
if (unlikely(!backing_file_func)) {
/* don't load "loop" module here */
backing_file_func = symbol_get(loop_backing_file);
if (unlikely(!backing_file_func))
/* "loop" module is not loaded */
return 0;
}
h_sb = h_adding->d_sb;
backing_file = backing_file_func(h_sb);
if (!backing_file)
return 0;
h_adding = backing_file->f_path.dentry;
/*
* h_adding can be local NFS.
* in this case aufs cannot detect the loop.
*/
if (unlikely(h_adding->d_sb == sb))
return 1;
return !!au_test_subdir(h_adding, sb->s_root);
}
/* true if a kernel thread named 'loop[0-9].*' accesses a file */
int au_test_loopback_kthread(void)
{
int ret;
struct task_struct *tsk = current;
char c, comm[sizeof(tsk->comm)];
ret = 0;
if (tsk->flags & PF_KTHREAD) {
get_task_comm(comm, tsk);
c = comm[4];
ret = ('0' <= c && c <= '9'
&& !strncmp(comm, "loop", 4));
}
return ret;
}
/* ---------------------------------------------------------------------- */
#define au_warn_loopback_step 16
static int au_warn_loopback_nelem = au_warn_loopback_step;
static unsigned long *au_warn_loopback_array;
void au_warn_loopback(struct super_block *h_sb)
{
int i, new_nelem;
unsigned long *a, magic;
static DEFINE_SPINLOCK(spin);
magic = h_sb->s_magic;
spin_lock(&spin);
a = au_warn_loopback_array;
for (i = 0; i < au_warn_loopback_nelem && *a; i++)
if (a[i] == magic) {
spin_unlock(&spin);
return;
}
/* h_sb is new to us, print it */
if (i < au_warn_loopback_nelem) {
a[i] = magic;
goto pr;
}
/* expand the array */
new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
a = au_kzrealloc(au_warn_loopback_array,
au_warn_loopback_nelem * sizeof(unsigned long),
new_nelem * sizeof(unsigned long), GFP_ATOMIC,
/*may_shrink*/0);
if (a) {
au_warn_loopback_nelem = new_nelem;
au_warn_loopback_array = a;
a[i] = magic;
goto pr;
}
spin_unlock(&spin);
AuWarn1("realloc failed, ignored\n");
return;
pr:
spin_unlock(&spin);
pr_warn("you may want to try another patch for loopback file "
"on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
}
int au_loopback_init(void)
{
int err;
struct super_block *sb __maybe_unused;
BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(unsigned long));
err = 0;
au_warn_loopback_array = kcalloc(au_warn_loopback_step,
sizeof(unsigned long), GFP_NOFS);
if (unlikely(!au_warn_loopback_array))
err = -ENOMEM;
return err;
}
void au_loopback_fin(void)
{
if (backing_file_func)
symbol_put(loop_backing_file);
au_kfree_try_rcu(au_warn_loopback_array);
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2005-2019 Junjiro R. Okajima
*/
/*
* support for loopback mount as a branch
*/
#ifndef __AUFS_LOOP_H__
#define __AUFS_LOOP_H__
#ifdef __KERNEL__
struct dentry;
struct super_block;
#ifdef CONFIG_AUFS_BDEV_LOOP
/* drivers/block/loop.c */
struct file *loop_backing_file(struct super_block *sb);
/* loop.c */
int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
int au_test_loopback_kthread(void);
void au_warn_loopback(struct super_block *h_sb);
int au_loopback_init(void);
void au_loopback_fin(void);
#else
AuStub(struct file *, loop_backing_file, return NULL)
AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
struct dentry *h_adding)
AuStubInt0(au_test_loopback_kthread, void)
AuStubVoid(au_warn_loopback, struct super_block *h_sb)
AuStubInt0(au_loopback_init, void)
AuStubVoid(au_loopback_fin, void)
#endif /* BLK_DEV_LOOP */
#endif /* __KERNEL__ */
#endif /* __AUFS_LOOP_H__ */
...@@ -193,9 +193,12 @@ static int __init aufs_init(void) ...@@ -193,9 +193,12 @@ static int __init aufs_init(void)
err = au_wkq_init(); err = au_wkq_init();
if (unlikely(err)) if (unlikely(err))
goto out_procfs; goto out_procfs;
err = au_hnotify_init(); err = au_loopback_init();
if (unlikely(err)) if (unlikely(err))
goto out_wkq; goto out_wkq;
err = au_hnotify_init();
if (unlikely(err))
goto out_loopback;
err = au_sysrq_init(); err = au_sysrq_init();
if (unlikely(err)) if (unlikely(err))
goto out_hin; goto out_hin;
...@@ -217,6 +220,8 @@ out_sysrq: ...@@ -217,6 +220,8 @@ out_sysrq:
au_sysrq_fin(); au_sysrq_fin();
out_hin: out_hin:
au_hnotify_fin(); au_hnotify_fin();
out_loopback:
au_loopback_fin();
out_wkq: out_wkq:
au_wkq_fin(); au_wkq_fin();
out_procfs: out_procfs:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment