From: George Wang <xuw2015@xxxxxxxxx> If we use the overlayfs mount point as the lowerdir of another overlayfs, the ->iterate will be called nestly. It's just like overlayfs2->iterate will call overlayfs1->iterate when we ls the overlayfs2 items. We turn off the lockdep to avoid the false positive warning in this situation, and trun on the lockdep when it finished. The following procedure can reproduce it: mkdir 1 1_lower 1_upper 1_work 2 2_upper 2_work mount -t overlay overlay 1 -o lowerdir=1_lower,upperdir=1_upper,workdir=1_work mount -t overlay overlay 2 -o lowerdir=1,upperdir=2_upper,workdir=2_work ls 2 Reported-by: Konstantin Khlebnikov <koct9i@xxxxxxxxx> Signed-off-by: George Wang <xuw2015@xxxxxxxxx> --- fs/overlayfs/readdir.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 70e9af5..3f7f99b 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -236,6 +236,31 @@ static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd) return err; } +/* + * If we use overlayfs as lower, the iterate_dir will be nest. This will + * trigger the lockdep deadlock warning, but actually, this is not deadlock. + * No one wants to see false positive warnings, so we use this wrapper + * function to keep silent in this situation. + */ +static inline int iterate_dir_silent(struct file *dir, struct dir_context *ctx) +{ + extern const struct file_operations ovl_dir_operations; + int err = 0; + int off = 0; + + if (dir->f_op == &ovl_dir_operations) { + lockdep_off(); + off = 1; + } + + err = iterate_dir(dir, ctx); + + if (off) + lockdep_on(); + + return err; +} + static inline int ovl_dir_read(struct path *realpath, struct ovl_readdir_data *rdd) { @@ -251,7 +276,7 @@ static inline int ovl_dir_read(struct path *realpath, do { rdd->count = 0; rdd->err = 0; - err = iterate_dir(realfile, &rdd->ctx); + err = iterate_dir_silent(realfile, &rdd->ctx); if (err >= 0) err = rdd->err; } while (!err && rdd->count); @@ -370,7 +395,7 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) ovl_dir_reset(file); if (od->is_real) - return iterate_dir(od->realfile, ctx); + return iterate_dir_silent(od->realfile, ctx); if (!od->cache) { struct ovl_dir_cache *cache; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html