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

aufs: dirwh option



This is a feature to optimize for rmdir and rename dir.
When the number of whiteouts under the target dir is very many, it may
take a long time to remove them all. To prevent this, 'dirwh=%d' option
specifies the watermark to decide when to remove them.

For details, see aufs manual in aufs-util.git.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent b3b9c456
......@@ -82,6 +82,8 @@ int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
unsigned int au_rdhash_est(loff_t sz);
int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
void au_nhash_wh_free(struct au_nhash *whlist);
int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
int limit);
int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
unsigned int d_type, aufs_bindex_t bindex);
......
......@@ -206,7 +206,7 @@ out:
static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
struct au_nhash *whlist, struct inode *dir)
{
int err;
int rmdir_later, err, dirwh;
struct dentry *h_dentry;
struct super_block *sb;
struct inode *inode;
......@@ -222,6 +222,16 @@ static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
inode = d_inode(dentry);
au_hn_free(au_hi(inode, bindex));
if (!au_test_fs_remote(h_dentry->d_sb)) {
dirwh = au_sbi(sb)->si_dirwh;
rmdir_later = (dirwh <= 1);
if (!rmdir_later)
rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
dirwh);
if (rmdir_later)
return rmdir_later;
}
err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
if (unlikely(err)) {
AuIOErr("rmdir %pd, b%d failed, %d. ignored\n",
......
......@@ -238,16 +238,26 @@ static int au_ren_or_cpup(struct au_ren_args *a)
/* cf. aufs_rmdir() */
static int au_ren_del_whtmp(struct au_ren_args *a)
{
int err;
struct inode *dir;
dir = a->dst_dir;
SiMustAnyLock(dir->i_sb);
au_nhash_wh_free(&a->thargs->whlist);
a->thargs->whlist = a->whlist;
a->whlist.nh_num = 0;
au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
dput(a->h_dst);
a->thargs = NULL;
if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
au_sbi(dir->i_sb)->si_dirwh)
|| au_test_fs_remote(a->h_dst->d_sb)) {
err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
if (unlikely(err))
pr_warn("failed removing whtmp dir %pd (%d), "
"ignored.\n", a->h_dst, err);
} else {
au_nhash_wh_free(&a->thargs->whlist);
a->thargs->whlist = a->whlist;
a->whlist.nh_num = 0;
au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
dput(a->h_dst);
a->thargs = NULL;
}
return 0;
}
......
......@@ -18,7 +18,7 @@ enum {
Opt_br,
Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
Opt_idel, Opt_imod,
Opt_rdcache, Opt_rdblk, Opt_rdhash,
Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
Opt_rdblk_def, Opt_rdhash_def,
Opt_xino, Opt_noxino,
Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
......@@ -54,6 +54,8 @@ static match_table_t options = {
{Opt_mod, "mod:%s"},
/* {Opt_imod, "imod:%d:%s"}, */
{Opt_dirwh, "dirwh=%d"},
{Opt_xino, "xino=%s"},
{Opt_noxino, "noxino"},
{Opt_trunc_xino, "trunc_xino"},
......@@ -518,6 +520,9 @@ static void dump_opts(struct au_opts *opts)
u.add->bindex, u.add->pathname, u.add->perm,
u.add->path.dentry);
break;
case Opt_dirwh:
AuDbg("dirwh %d\n", opt->dirwh);
break;
case Opt_rdcache:
AuDbg("rdcache %d\n", opt->rdcache);
break;
......@@ -990,6 +995,13 @@ int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
opt->type = token;
break;
case Opt_dirwh:
if (unlikely(match_int(&a->args[0], &opt->dirwh)))
break;
err = 0;
opt->type = token;
break;
case Opt_rdcache:
if (unlikely(match_int(&a->args[0], &n))) {
pr_err("bad integer in %s\n", opt_str);
......@@ -1216,6 +1228,10 @@ static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
break;
case Opt_dirwh:
sbinfo->si_dirwh = opt->dirwh;
break;
case Opt_rdcache:
sbinfo->si_rdcache
= msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
......
......@@ -138,6 +138,7 @@ struct au_opt {
struct au_opt_add add;
struct au_opt_del del;
struct au_opt_mod mod;
int dirwh;
int rdcache;
unsigned int rdblk;
unsigned int rdhash;
......
......@@ -88,6 +88,7 @@ int au_si_alloc(struct super_block *sb)
sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
sbinfo->si_rdblk = AUFS_RDBLK_DEF;
sbinfo->si_rdhash = AUFS_RDHASH_DEF;
sbinfo->si_dirwh = AUFS_DIRWH_DEF;
for (i = 0; i < AuPlink_NHASH; i++)
INIT_HLIST_BL_HEAD(sbinfo->si_plink + i);
......
......@@ -268,6 +268,8 @@ static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
if (v != AuWbrCopyup_Def)
seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
AuUInt(RDCACHE, rdcache, v);
......
......@@ -130,6 +130,14 @@ struct au_sbinfo {
unsigned int si_rdblk; /* deblk size */
unsigned int si_rdhash; /* hash size */
/*
* If the number of whiteouts are larger than si_dirwh, leave all of
* them after au_whtmp_ren to reduce the cost of rmdir(2).
* future fsck.aufs or kernel thread will remove them later.
* Otherwise, remove all whiteouts and the dir in rmdir(2).
*/
unsigned int si_dirwh;
/* pseudo_link list */
struct hlist_bl_head si_plink[AuPlink_NHASH];
wait_queue_head_t si_plink_wq;
......
......@@ -141,6 +141,24 @@ static void au_nhash_de_free(struct au_nhash *delist)
/* ---------------------------------------------------------------------- */
int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
int limit)
{
int num;
unsigned int u, n;
struct hlist_head *head;
struct au_vdir_wh *pos;
num = 0;
n = whlist->nh_num;
head = whlist->nh_head;
for (u = 0; u < n; u++, head++)
hlist_for_each_entry(pos, head, wh_hash)
if (pos->wh_bindex == btgt && ++num > limit)
return 1;
return 0;
}
static struct hlist_head *au_name_hash(struct au_nhash *nhash,
unsigned char *name,
unsigned int len)
......
......@@ -73,6 +73,7 @@ typedef int16_t aufs_bindex_t;
#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
#define AUFS_XINO_DEF_SEC 30 /* seconds */
#define AUFS_XINO_DEF_TRUNC 45 /* percentage */
#define AUFS_DIRWH_DEF 3
#define AUFS_RDCACHE_DEF 10 /* seconds */
#define AUFS_RDCACHE_MAX 3600 /* seconds */
#define AUFS_RDBLK_DEF 512 /* bytes */
......
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