needs_lookup_union() tests if a path could possibly require a union lookup. Signed-off-by: Valerie Aurora <vaurora@xxxxxxxxxx> --- fs/union.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/union.h | 2 ++ 2 files changed, 51 insertions(+), 0 deletions(-) diff --git a/fs/union.c b/fs/union.c index bc53066..a9427bf 100644 --- a/fs/union.c +++ b/fs/union.c @@ -127,3 +127,52 @@ int union_create_topmost_dir(struct path *parent, struct qstr *name, return res; } + +/** + * needs_lookup_union - Avoid union lookup when not necessary + * + * @parent_path: path of the parent directory + * @path: path of the lookup target + * + * Check to see if the target needs union lookup - that is, needs its + * union stack constructed. Two cases need union lookup in a unioned + * parent directory: the target is a directory without a union stack, + * or the target is a negative dentry. + * + * Returns 0 if this dentry does not need union lookup. Returns 1 if + * it is possible this dentry needs union lookup. + */ + +int needs_lookup_union(struct path *parent_path, struct path *path) +{ + if (!IS_DIR_UNIONED(parent_path->dentry)) + return 0; + + /* Root dir union stack created at mount (if this is a unioned mnt) */ + if (IS_ROOT(path->dentry)) + return 0; + + /* Union stack for target already created, clearly */ + if (IS_DIR_UNIONED(path->dentry)) + return 0; + + if (d_is_whiteout(path->dentry)) + return 0; + + if (IS_OPAQUE(parent_path->dentry->d_inode) && + !d_is_fallthru(path->dentry)) + return 0; + + /* Non-directories don't need union stacks */ + if (path->dentry->d_inode && + !S_ISDIR(path->dentry->d_inode->i_mode)) + return 0; + + /* + * XXX Things with nothing below them in a union dir + * (including negative dentries) must always go through union + * lookup. This is like negative dentries in the dcache. + * Write some optimization for this case. + */ + return 1; +} diff --git a/fs/union.h b/fs/union.h index c496823..0c8fbca 100644 --- a/fs/union.h +++ b/fs/union.h @@ -56,6 +56,7 @@ extern void d_free_unions(struct dentry *); extern int union_add_dir(struct path *, struct path *, unsigned int); extern int union_create_topmost_dir(struct path *, struct qstr *, struct path *, struct path *); +extern int needs_lookup_union(struct path *, struct path *); static inline struct path *union_find_dir(struct dentry *dentry, unsigned int layer) { @@ -72,6 +73,7 @@ static inline struct path *union_find_dir(struct dentry *dentry, #define union_add_dir(x, y, z) ({ BUG(); (0); }) #define union_find_dir(x, y) ({ BUG(); (NULL); }) #define union_create_topmost_dir(w, x, y, z) ({ BUG(); (0); }) +#define needs_lookup_union(x, y) ({ (0); }) #endif /* CONFIG_UNION_MOUNT */ #endif /* __KERNEL__ */ -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html