diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c index 37bb9af..74d7922 100644 --- a/fs/aufs/opts.c +++ b/fs/aufs/opts.c @@ -251,8 +251,12 @@ const char *au_optstr_udba(int udba) /* ---------------------------------------------------------------------- */ static match_table_t au_wbr_create_policy = { - {AuWbrCreate_TDP, "tdp"}, - {AuWbrCreate_TDP, "top-down-parent"}, + {AuWbrCreate_TDP_B, "tdp:b"}, + {AuWbrCreate_TDP_B, "top-down-parent:b"}, + {AuWbrCreate_TDP_B, "tdp"}, + {AuWbrCreate_TDP_B, "top-down-parent"}, + {AuWbrCreate_TDP_T, "tdp:t"}, + {AuWbrCreate_TDP_T, "top-down-parent:t"}, {AuWbrCreate_RR, "rr"}, {AuWbrCreate_RR, "round-robin"}, {AuWbrCreate_MFS, "mfs"}, diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h index e788621..bdf1a69 100644 --- a/fs/aufs/opts.h +++ b/fs/aufs/opts.h @@ -95,7 +95,8 @@ static inline unsigned int au_opts_plink(unsigned int mntflags) /* policies to select one among multiple writable branches */ enum { - AuWbrCreate_TDP, /* top down parent */ + AuWbrCreate_TDP_B, /* top down parent, fallback "buttom up" */ + AuWbrCreate_TDP_T, /* top down parent, fallback "top down" */ AuWbrCreate_RR, /* round robin */ AuWbrCreate_MFS, /* most free space */ AuWbrCreate_MFSV, /* mfs with seconds */ @@ -104,7 +105,7 @@ enum { AuWbrCreate_PMFS, /* parent and mfs */ AuWbrCreate_PMFSV, /* parent and mfs with seconds */ - AuWbrCreate_Def = AuWbrCreate_TDP + AuWbrCreate_Def = AuWbrCreate_TDP_B }; enum { diff --git a/fs/aufs/super.c b/fs/aufs/super.c index 1afab45..25a227d 100644 --- a/fs/aufs/super.c +++ b/fs/aufs/super.c @@ -119,7 +119,8 @@ static void au_show_wbr_create(struct seq_file *m, int v, seq_printf(m, ",create="); pat = au_optstr_wbr_create(v); switch (v) { - case AuWbrCreate_TDP: + case AuWbrCreate_TDP_B: + case AuWbrCreate_TDP_T: case AuWbrCreate_RR: case AuWbrCreate_MFS: case AuWbrCreate_PMFS: diff --git a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c index 7503ac3..be87c9f 100644 --- a/fs/aufs/wbr_policy.c +++ b/fs/aufs/wbr_policy.c @@ -268,7 +268,7 @@ static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex) } /* top down parent */ -static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused) +static int au_wbr_do_create_tdp(struct dentry *dentry) { int err; aufs_bindex_t bstart, bindex; @@ -295,12 +295,49 @@ static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused) } dput(parent); - /* bottom up here */ - if (unlikely(err < 0)) { - err = au_wbr_bu(sb, bstart - 1); - if (err >= 0) - err = au_wbr_nonopq(dentry, err); - } +out: + AuDbg("b%d\n", err); + return err; +} + +/* top down parent:bottom up */ +static int au_wbr_create_tdp_b(struct dentry *dentry, int isdir __maybe_unused) +{ + int err; + aufs_bindex_t bstart; + + err = au_wbr_do_create_tdp(dentry); + if (err >= 0) + goto out; + + bstart = au_dbstart(dentry); + err = au_wbr_bu(dentry->d_sb, bstart - 1); + if (err >= 0) + err = au_wbr_nonopq(dentry, err); + +out: + AuDbg("b%d\n", err); + return err; +} + +/* top down parent:top down */ +static int au_wbr_create_tdp_t(struct dentry *dentry, int isdir __maybe_unused) +{ + int err; + aufs_bindex_t bindex, bend; + struct super_block *sb; + + err = au_wbr_do_create_tdp(dentry); + if (err >= 0) + goto out; + + sb = dentry->d_sb; + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) + if (!au_br_rdonly(au_sbr(sb, bindex))) { + err = bindex; + break; + } out: AuDbg("b%d\n", err); @@ -543,7 +580,8 @@ static int au_wbr_create_pmfs(struct dentry *dentry, int isdir) struct dentry *parent, *h_parent; struct au_branch *br; - err = au_wbr_create_tdp(dentry, isdir); + /* should we support tdp_t too? */ + err = au_wbr_create_tdp_b(dentry, isdir); if (unlikely(err < 0)) goto out; parent = dget_parent(dentry); @@ -592,7 +630,8 @@ out: /* top down parent */ static int au_wbr_copyup_tdp(struct dentry *dentry) { - return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0); + /* should we support tdp_t too? */ + return au_wbr_create_tdp_b(dentry, /*isdir, anything is ok*/0); } /* bottom up parent */ @@ -658,8 +697,11 @@ struct au_wbr_copyup_operations au_wbr_copyup_ops[] = { }; struct au_wbr_create_operations au_wbr_create_ops[] = { - [AuWbrCreate_TDP] = { - .create = au_wbr_create_tdp + [AuWbrCreate_TDP_B] = { + .create = au_wbr_create_tdp_b + }, + [AuWbrCreate_TDP_T] = { + .create = au_wbr_create_tdp_t }, [AuWbrCreate_RR] = { .create = au_wbr_create_rr,