On Fri, Jun 26, 2015 at 10:04 AM, <xuw2015@xxxxxxxxx> wrote: > 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> I don't like this solution. It looks like a piece of duct tape. Stacking several layers of overlayfs is useless. I think it safer to forbid that setup. > --- > 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