Commit 27c33497 authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: users' direct branch access



Aufs allows users' direct branch access (UDBA), ie. by-passing aufs.
Of course it will make aufs inode/dentry-caches obsolete. In order to
detect such change by the several tests, "udba=" option is introduced.

For details, see lookup.txt in later commit.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 2ef06b5a
......@@ -659,7 +659,8 @@ int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent,
}
mnt_flags = au_mntflags(sb);
if (!isdir
if (!au_opt_test(mnt_flags, UDBA_NONE)
&& !isdir
&& au_opt_test(mnt_flags, XINO)
&& (h_inode->i_nlink == 1
|| (h_inode->i_state & I_LINKABLE))
......@@ -1208,7 +1209,7 @@ int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
pin_orig = cpg->pin;
au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT,
AuLsc_I_PARENT3, AuPin_DI_LOCKED);
AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED);
cpg->pin = &wh_pin;
}
......@@ -1261,7 +1262,7 @@ int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
goto out;
au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
AuPin_MNT_WRITE);
au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
/* do not use au_dpage */
real_parent = parent;
......
......@@ -171,7 +171,8 @@ int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
au_update_dbtop(dentry);
}
err = npositive;
if (unlikely(au_dbtop(dentry) < 0)) {
if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE)
&& au_dbtop(dentry) < 0)) {
err = -EIO;
AuIOErr("both of real entry and whiteout found, %pd, err %d\n",
dentry, err);
......@@ -326,16 +327,17 @@ out:
return err;
}
int au_h_verify(struct dentry *h_dentry, struct inode *h_dir,
int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
struct dentry *h_parent, struct au_branch *br)
{
int err;
err = 0;
if (!au_test_fs_remote(h_dentry->d_sb)) {
if (udba == AuOpt_UDBA_REVAL
&& !au_test_fs_remote(h_dentry->d_sb)) {
IMustLock(h_dir);
err = (d_inode(h_dentry->d_parent) != h_dir);
} else
} else if (udba != AuOpt_UDBA_NONE)
err = au_h_verify_dentry(h_dentry, h_parent, br);
return err;
......
......@@ -51,7 +51,7 @@ struct au_do_lookup_args {
/* dentry.c */
struct au_branch;
struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
int au_h_verify(struct dentry *h_dentry, struct inode *h_dir,
int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
struct dentry *h_parent, struct au_branch *br);
int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
......
......@@ -32,8 +32,8 @@ int au_pin_hdir_lock(struct au_pin *p)
err = 0;
if (p->h_dentry)
err = au_h_verify(p->h_dentry, p->hdir->hi_inode, p->h_parent,
p->br);
err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode,
p->h_parent, p->br);
out:
return err;
......@@ -193,9 +193,10 @@ out:
void au_pin_init(struct au_pin *p, struct dentry *dentry,
aufs_bindex_t bindex, int lsc_di, int lsc_hi,
unsigned char flags)
unsigned int udba, unsigned char flags)
{
p->dentry = dentry;
p->udba = udba;
p->lsc_di = lsc_di;
p->lsc_hi = lsc_hi;
p->flags = flags;
......@@ -212,9 +213,9 @@ void au_pin_init(struct au_pin *p, struct dentry *dentry,
}
int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
unsigned char flags)
unsigned int udba, unsigned char flags)
{
au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
flags);
udba, flags);
return au_do_pin(pin);
}
......@@ -59,6 +59,7 @@ struct au_icntnr {
struct au_pin {
/* input */
struct dentry *dentry;
unsigned int udba;
unsigned char lsc_di, lsc_hi, flags;
aufs_bindex_t bindex;
......@@ -100,9 +101,9 @@ int au_test_h_perm_sio(struct inode *h_inode, int mask);
struct dentry *au_pinned_h_parent(struct au_pin *pin);
void au_pin_init(struct au_pin *pin, struct dentry *dentry,
aufs_bindex_t bindex, int lsc_di, int lsc_hi,
unsigned char flags);
unsigned int udba, unsigned char flags);
int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
unsigned char flags) __must_check;
unsigned int udba, unsigned char flags) __must_check;
int au_do_pin(struct au_pin *pin) __must_check;
void au_unpin(struct au_pin *pin);
......
......@@ -252,6 +252,27 @@ void au_optstr_br_perm(au_br_perm_str_t *str, int perm)
/* ---------------------------------------------------------------------- */
static match_table_t udbalevel = {
{AuOpt_UDBA_REVAL, "reval"},
{AuOpt_UDBA_NONE, "none"},
{-1, NULL}
};
/* re-commit later */ __maybe_unused
static int noinline_for_stack udba_val(char *str)
{
substring_t args[MAX_OPT_ARGS];
return match_token(str, udbalevel, args);
}
const char *au_optstr_udba(int udba)
{
return au_parser_pattern(udba, udbalevel);
}
/* ---------------------------------------------------------------------- */
static match_table_t au_wbr_create_policy = {
{AuWbrCreate_TDP, "tdp"},
{AuWbrCreate_TDP, "top-down-parent"},
......@@ -1063,3 +1084,10 @@ int au_opts_mount(struct super_block *sb, struct au_opts *opts)
out:
return err;
}
/* ---------------------------------------------------------------------- */
unsigned int au_opt_udba(struct super_block *sb)
{
return au_mntflags(sb) & AuOptMask_UDBA;
}
......@@ -22,13 +22,23 @@ struct file;
#define AuOpt_XINO 1 /* external inode number bitmap
and translation table */
#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
#define AuOpt_UDBA_REVAL (1 << 3)
#define AuOpt_PLINK (1 << 6) /* pseudo-link */
#define AuOpt_Def (AuOpt_XINO \
| AuOpt_UDBA_REVAL \
| AuOpt_PLINK)
#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
| AuOpt_UDBA_REVAL)
#define au_opt_test(flags, name) (flags & AuOpt_##name)
#define au_opt_set(flags, name) do { \
BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
((flags) |= AuOpt_##name); \
} while (0)
#define au_opt_set_udba(flags, name) do { \
(flags) &= ~AuOptMask_UDBA; \
((flags) |= AuOpt_##name); \
} while (0)
#define au_opt_clr(flags, name) do { \
......@@ -128,6 +138,7 @@ struct au_opts {
/* opts.c */
void au_optstr_br_perm(au_br_perm_str_t *str, int perm);
const char *au_optstr_udba(int udba);
const char *au_optstr_wbr_copyup(int wbr_copyup);
const char *au_optstr_wbr_create(int wbr_create);
......@@ -138,5 +149,7 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
unsigned int pending);
int au_opts_mount(struct super_block *sb, struct au_opts *opts);
unsigned int au_opt_udba(struct super_block *sb);
#endif /* __KERNEL__ */
#endif /* __AUFS_OPTS_H__ */
......@@ -499,7 +499,8 @@ static void reinit_br_wh(void *arg)
inode_lock_nested(hdir->hi_inode, AuLsc_I_PARENT);
wbr_wh_write_lock(wbr);
err = au_h_verify(wbr->wbr_whbase, hdir->hi_inode, h_root, a->br);
err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
h_root, a->br);
if (!err) {
h_path.dentry = wbr->wbr_whbase;
h_path.mnt = au_br_mnt(a->br);
......
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