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

aufs: dentry op, opt-out ->d_revalidate()



Optimize out ->d_revalidate() if possible.
If the refreshing failed, then ->d_revalidate() remains. In this case,
aufs has two types of dentries. One has ->d_revalidate, the other
doesn't. I am afraid it will confuse me someday.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 5531888f
...@@ -655,6 +655,28 @@ out: ...@@ -655,6 +655,28 @@ out:
return err; return err;
} }
void au_refresh_dop(struct dentry *dentry, int force_reval)
{
const struct dentry_operations *dop
= force_reval ? &aufs_dop : dentry->d_sb->s_d_op;
static const unsigned int mask
= DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE;
BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags));
if (dentry->d_op == dop)
return;
AuDbg("%pd\n", dentry);
spin_lock(&dentry->d_lock);
if (dop == &aufs_dop)
dentry->d_flags |= mask;
else
dentry->d_flags &= ~mask;
dentry->d_op = dop;
spin_unlock(&dentry->d_lock);
}
int au_refresh_dentry(struct dentry *dentry, struct dentry *parent) int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
{ {
int err, ebrange, nbr; int err, ebrange, nbr;
...@@ -1064,3 +1086,8 @@ const struct dentry_operations aufs_dop = { ...@@ -1064,3 +1086,8 @@ const struct dentry_operations aufs_dop = {
.d_weak_revalidate = aufs_d_revalidate, .d_weak_revalidate = aufs_d_revalidate,
.d_release = aufs_d_release .d_release = aufs_d_release
}; };
/* aufs_dop without d_revalidate */
const struct dentry_operations aufs_dop_noreval = {
.d_release = aufs_d_release
};
...@@ -49,7 +49,7 @@ struct au_do_lookup_args { ...@@ -49,7 +49,7 @@ struct au_do_lookup_args {
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* dentry.c */ /* dentry.c */
extern const struct dentry_operations aufs_dop; extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
struct au_branch; struct au_branch;
struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent); struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
...@@ -60,6 +60,7 @@ int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, ...@@ -60,6 +60,7 @@ int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh); int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
int au_refresh_dentry(struct dentry *dentry, struct dentry *parent); int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
int au_reval_dpath(struct dentry *dentry, unsigned int sigen); int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
void au_refresh_dop(struct dentry *dentry, int force_reval);
/* dinfo.c */ /* dinfo.c */
void au_di_init_once(void *_di); void au_di_init_once(void *_di);
......
...@@ -1062,10 +1062,10 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags, ...@@ -1062,10 +1062,10 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
{ {
int err; int err;
aufs_bindex_t bindex, bbot; aufs_bindex_t bindex, bbot;
unsigned char do_plink, skip, do_free; unsigned char do_plink, skip, do_free, can_no_dreval;
struct au_branch *br; struct au_branch *br;
struct au_wbr *wbr; struct au_wbr *wbr;
struct dentry *root; struct dentry *root, *dentry;
struct inode *dir, *h_dir; struct inode *dir, *h_dir;
struct au_sbinfo *sbinfo; struct au_sbinfo *sbinfo;
struct au_hinode *hdir; struct au_hinode *hdir;
...@@ -1084,6 +1084,8 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags, ...@@ -1084,6 +1084,8 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
root = sb->s_root; root = sb->s_root;
dir = d_inode(root); dir = d_inode(root);
do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK); do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending),
UDBA_NONE);
bbot = au_sbbot(sb); bbot = au_sbbot(sb);
for (bindex = 0; !err && bindex <= bbot; bindex++) { for (bindex = 0; !err && bindex <= bbot; bindex++) {
skip = 0; skip = 0;
...@@ -1123,6 +1125,15 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags, ...@@ -1123,6 +1125,15 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
if (wbr) if (wbr)
wbr_wh_read_unlock(wbr); wbr_wh_read_unlock(wbr);
if (can_no_dreval) {
dentry = br->br_path.dentry;
spin_lock(&dentry->d_lock);
if (dentry->d_flags &
(DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE))
can_no_dreval = 0;
spin_unlock(&dentry->d_lock);
}
if (skip) if (skip)
continue; continue;
...@@ -1141,6 +1152,11 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags, ...@@ -1141,6 +1152,11 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
} }
} }
if (can_no_dreval)
au_fset_si(sbinfo, NO_DREVAL);
else
au_fclr_si(sbinfo, NO_DREVAL);
return err; return err;
} }
...@@ -1238,6 +1254,7 @@ out: ...@@ -1238,6 +1254,7 @@ out:
int au_opts_remount(struct super_block *sb, struct au_opts *opts) int au_opts_remount(struct super_block *sb, struct au_opts *opts)
{ {
int err, rerr; int err, rerr;
unsigned char no_dreval;
struct inode *dir; struct inode *dir;
struct au_opt_xino *opt_xino; struct au_opt_xino *opt_xino;
struct au_opt *opt; struct au_opt *opt;
...@@ -1263,10 +1280,14 @@ int au_opts_remount(struct super_block *sb, struct au_opts *opts) ...@@ -1263,10 +1280,14 @@ int au_opts_remount(struct super_block *sb, struct au_opts *opts)
AuTraceErr(err); AuTraceErr(err);
/* go on even err */ /* go on even err */
no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL);
rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0); rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
if (unlikely(rerr && !err)) if (unlikely(rerr && !err))
err = rerr; err = rerr;
if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL))
au_fset_opts(opts->flags, REFRESH_DOP);
if (au_ftest_opts(opts->flags, TRUNC_XIB)) { if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
rerr = au_xib_trunc(sb); rerr = au_xib_trunc(sb);
if (unlikely(rerr && !err)) if (unlikely(rerr && !err))
...@@ -1275,7 +1296,10 @@ int au_opts_remount(struct super_block *sb, struct au_opts *opts) ...@@ -1275,7 +1296,10 @@ int au_opts_remount(struct super_block *sb, struct au_opts *opts)
/* will be handled by the caller */ /* will be handled by the caller */
if (!au_ftest_opts(opts->flags, REFRESH) if (!au_ftest_opts(opts->flags, REFRESH)
&& (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO))) && (opts->given_udba
|| au_opt_test(sbinfo->si_mntflags, XINO)
|| au_ftest_opts(opts->flags, REFRESH_DOP)
))
au_fset_opts(opts->flags, REFRESH); au_fset_opts(opts->flags, REFRESH);
AuDbg("status 0x%x\n", opts->flags); AuDbg("status 0x%x\n", opts->flags);
......
...@@ -135,6 +135,7 @@ struct au_opt { ...@@ -135,6 +135,7 @@ struct au_opt {
#define AuOpts_REFRESH (1 << 1) #define AuOpts_REFRESH (1 << 1)
#define AuOpts_TRUNC_XIB (1 << 2) #define AuOpts_TRUNC_XIB (1 << 2)
#define AuOpts_REFRESH_DYAOP (1 << 3) #define AuOpts_REFRESH_DYAOP (1 << 3)
#define AuOpts_REFRESH_DOP (1 << 4)
#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name) #define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
#define au_fset_opts(flags, name) \ #define au_fset_opts(flags, name) \
do { (flags) |= AuOpts_##name; } while (0) do { (flags) |= AuOpts_##name; } while (0)
......
...@@ -460,7 +460,7 @@ static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags, ...@@ -460,7 +460,7 @@ static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen, static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
struct au_sbinfo *sbinfo, struct au_sbinfo *sbinfo,
const unsigned int dir_flags) const unsigned int dir_flags, unsigned int do_dop)
{ {
int err; int err;
struct dentry *parent; struct dentry *parent;
...@@ -483,11 +483,17 @@ static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen, ...@@ -483,11 +483,17 @@ static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
} }
dput(parent); dput(parent);
if (!err) {
if (do_dop)
au_refresh_dop(dentry, /*force_reval*/0);
} else
au_refresh_dop(dentry, /*force_reval*/1);
AuTraceErr(err); AuTraceErr(err);
return err; return err;
} }
static int au_refresh_d(struct super_block *sb) static int au_refresh_d(struct super_block *sb, unsigned int do_dop)
{ {
int err, i, j, ndentry, e; int err, i, j, ndentry, e;
unsigned int sigen; unsigned int sigen;
...@@ -498,6 +504,9 @@ static int au_refresh_d(struct super_block *sb) ...@@ -498,6 +504,9 @@ static int au_refresh_d(struct super_block *sb)
struct dentry *root = sb->s_root; struct dentry *root = sb->s_root;
const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1); const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1);
if (do_dop)
au_refresh_dop(root, /*force_reval*/0);
err = au_dpages_init(&dpages, GFP_NOFS); err = au_dpages_init(&dpages, GFP_NOFS);
if (unlikely(err)) if (unlikely(err))
goto out; goto out;
...@@ -513,7 +522,8 @@ static int au_refresh_d(struct super_block *sb) ...@@ -513,7 +522,8 @@ static int au_refresh_d(struct super_block *sb)
ndentry = dpage->ndentry; ndentry = dpage->ndentry;
for (j = 0; j < ndentry; j++) { for (j = 0; j < ndentry; j++) {
d = dentries[j]; d = dentries[j];
e = au_do_refresh_d(d, sigen, sbinfo, dir_flags); e = au_do_refresh_d(d, sigen, sbinfo, dir_flags,
do_dop);
if (unlikely(e && !err)) if (unlikely(e && !err))
err = e; err = e;
/* go on even err */ /* go on even err */
...@@ -563,7 +573,7 @@ out: ...@@ -563,7 +573,7 @@ out:
return err; return err;
} }
static void au_remount_refresh(struct super_block *sb) static void au_remount_refresh(struct super_block *sb, unsigned int do_dop)
{ {
int err, e; int err, e;
unsigned int udba; unsigned int udba;
...@@ -571,9 +581,11 @@ static void au_remount_refresh(struct super_block *sb) ...@@ -571,9 +581,11 @@ static void au_remount_refresh(struct super_block *sb)
struct dentry *root; struct dentry *root;
struct inode *inode; struct inode *inode;
struct au_branch *br; struct au_branch *br;
struct au_sbinfo *sbi;
au_sigen_inc(sb); au_sigen_inc(sb);
au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR); sbi = au_sbi(sb);
au_fclr_si(sbi, FAILED_REFRESH_DIR);
root = sb->s_root; root = sb->s_root;
DiMustNoWaiters(root); DiMustNoWaiters(root);
...@@ -592,8 +604,19 @@ static void au_remount_refresh(struct super_block *sb) ...@@ -592,8 +604,19 @@ static void au_remount_refresh(struct super_block *sb)
} }
au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1)); au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
if (do_dop) {
if (au_ftest_si(sbi, NO_DREVAL)) {
AuDebugOn(sb->s_d_op == &aufs_dop_noreval);
sb->s_d_op = &aufs_dop_noreval;
} else {
AuDebugOn(sb->s_d_op == &aufs_dop);
sb->s_d_op = &aufs_dop;
}
pr_info("reset to %ps\n", sb->s_d_op);
}
di_write_unlock(root); di_write_unlock(root);
err = au_refresh_d(sb); err = au_refresh_d(sb, do_dop);
e = au_refresh_i(sb); e = au_refresh_i(sb);
if (unlikely(e && !err)) if (unlikely(e && !err))
err = e; err = e;
...@@ -670,7 +693,7 @@ static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) ...@@ -670,7 +693,7 @@ static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
au_opts_free(&opts); au_opts_free(&opts);
if (au_ftest_opts(opts.flags, REFRESH)) if (au_ftest_opts(opts.flags, REFRESH))
au_remount_refresh(sb); au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_DOP));
if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) { if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
mntflags = au_mntflags(sb); mntflags = au_mntflags(sb);
...@@ -747,6 +770,7 @@ static int aufs_fill_super(struct super_block *sb, void *raw_data, ...@@ -747,6 +770,7 @@ static int aufs_fill_super(struct super_block *sb, void *raw_data,
struct au_opts opts = { struct au_opts opts = {
.opt = NULL .opt = NULL
}; };
struct au_sbinfo *sbinfo;
struct dentry *root; struct dentry *root;
struct inode *inode; struct inode *inode;
char *arg = raw_data; char *arg = raw_data;
...@@ -767,6 +791,7 @@ static int aufs_fill_super(struct super_block *sb, void *raw_data, ...@@ -767,6 +791,7 @@ static int aufs_fill_super(struct super_block *sb, void *raw_data,
err = au_si_alloc(sb); err = au_si_alloc(sb);
if (unlikely(err)) if (unlikely(err))
goto out_opts; goto out_opts;
sbinfo = au_sbi(sb);
/* all timestamps always follow the ones on the branch */ /* all timestamps always follow the ones on the branch */
sb->s_flags |= SB_NOATIME | SB_NODIRATIME; sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
...@@ -801,6 +826,11 @@ static int aufs_fill_super(struct super_block *sb, void *raw_data, ...@@ -801,6 +826,11 @@ static int aufs_fill_super(struct super_block *sb, void *raw_data,
aufs_write_lock(root); aufs_write_lock(root);
err = au_opts_mount(sb, &opts); err = au_opts_mount(sb, &opts);
au_opts_free(&opts); au_opts_free(&opts);
if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
sb->s_d_op = &aufs_dop_noreval;
pr_info("%ps\n", sb->s_d_op);
au_refresh_dop(root, /*force_reval*/0);
}
aufs_write_unlock(root); aufs_write_unlock(root);
inode_unlock(inode); inode_unlock(inode);
if (!err) if (!err)
...@@ -810,7 +840,7 @@ out_root: ...@@ -810,7 +840,7 @@ out_root:
dput(root); dput(root);
sb->s_root = NULL; sb->s_root = NULL;
out_info: out_info:
kobject_put(&au_sbi(sb)->si_kobj); kobject_put(&sbinfo->si_kobj);
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
out_opts: out_opts:
free_page((unsigned long)opts.opt); free_page((unsigned long)opts.opt);
...@@ -853,7 +883,7 @@ static void aufs_kill_sb(struct super_block *sb) ...@@ -853,7 +883,7 @@ static void aufs_kill_sb(struct super_block *sb)
sbinfo->si_wbr_create_ops->fin(sb); sbinfo->si_wbr_create_ops->fin(sb);
if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) { if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE); au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
au_remount_refresh(sb); au_remount_refresh(sb, /*do_idop*/0);
} }
if (au_opt_test(sbinfo->si_mntflags, PLINK)) if (au_opt_test(sbinfo->si_mntflags, PLINK))
au_plink_put(sb, /*verbose*/1); au_plink_put(sb, /*verbose*/1);
......
...@@ -156,6 +156,8 @@ struct au_sbinfo { ...@@ -156,6 +156,8 @@ struct au_sbinfo {
* if it is false, refreshing dirs at access time is unnecessary * if it is false, refreshing dirs at access time is unnecessary
*/ */
#define AuSi_FAILED_REFRESH_DIR 1 #define AuSi_FAILED_REFRESH_DIR 1
/* add later */
#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */
static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
unsigned int flag) unsigned int flag)
......
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