On Mon, Oct 07, 2024 at 04:19:21PM +0200, Amir Goldstein wrote: > +static int ovl_real_fdget_path(const struct file *file, struct fd *real, > + struct path *realpath) > - if (allow_meta) { > - ovl_path_real(dentry, &realpath); > - } else { > - /* lazy lookup and verify of lowerdata */ > - err = ovl_verify_lowerdata(dentry); This check went > - if (err) > - return err; > - > - ovl_path_realdata(dentry, &realpath); > - } > @@ -138,7 +129,33 @@ static int ovl_real_fdget(const struct file *file, struct fd *real) > return 0; > } > > - return ovl_real_fdget_meta(file, real, false); > + /* lazy lookup and verify of lowerdata */ > + err = ovl_verify_lowerdata(dentry); ... here > + if (err) > + return err; > + > + ovl_path_realdata(dentry, &realpath); > +static int ovl_upper_fdget(const struct file *file, struct fd *real, bool data) > +{ > + struct dentry *dentry = file_dentry(file); > + struct path realpath; > + enum ovl_path_type type; > + > + if (data) > + type = ovl_path_realdata(dentry, &realpath); ... but not here. I can see the point of not doing that in ->fsync() after we'd already done ovl_verify_lowerdata() at open time, but what's different about ->read_iter() and friends that also come only after ->open()? IOW, why is fdatasync() different from other data-access cases?