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
sounds like philosophy or something, but in technically it
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
bool "Debug aufs"
help
......
......@@ -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_SYSFS) += sysfs.o
aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
aufs-$(CONFIG_AUFS_EXPORT) += export.o
......
......@@ -35,6 +35,7 @@
#include "hbl.h"
#include "inode.h"
#include "lcnt.h"
#include "loop.h"
#include "module.h"
#include "opts.h"
#include "rwsem.h"
......
......@@ -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,
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;
if (h_adding->d_sb != h_root->d_sb)
return 0;
......
......@@ -345,6 +345,13 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
if (IS_ERR(h_file))
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);
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)
err = au_wkq_init();
if (unlikely(err))
goto out_procfs;
err = au_hnotify_init();
err = au_loopback_init();
if (unlikely(err))
goto out_wkq;
err = au_hnotify_init();
if (unlikely(err))
goto out_loopback;
err = au_sysrq_init();
if (unlikely(err))
goto out_hin;
......@@ -217,6 +220,8 @@ out_sysrq:
au_sysrq_fin();
out_hin:
au_hnotify_fin();
out_loopback:
au_loopback_fin();
out_wkq:
au_wkq_fin();
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