Try to use the new vfs rename flag RENAME_DT_UNKNOWN, to request from underlying file system to mark copy up directory entries as DT_UNKNOWN instead of their actual file type. When copy ups are classified as DT_UNKNOWN, ovl_dir_read_merged() can distinguish between copy up to opaque objects without having to check the extended attribute trusted.overlay.inode on the iterated entries. This will allow to know if upper d_inode value needs to be substitued with lower d_inode value. Because this is only done for optimization, it is not a problem if file system does not respect the new RENAME_DT_UNKNOWN flag, which is most likely the case, so we retry the rename without the flag. This patch does not implement the actual optimization. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/overlayfs/copy_up.c | 8 +++++++- fs/overlayfs/overlayfs.h | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index f57043d..bcbcef5 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -298,7 +298,13 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, if (err) goto out_cleanup; - err = ovl_do_rename(wdir, newdentry, udir, upper, 0); + /* + * Mark copy up objects in upper as DT_UNKNOWN, so it easy to + * distinguish them from opaque objects in iterate_dir(). + * File system repair tools may re-classify the file type + * and that will break optimization, but not functionality. + */ + err = ovl_do_rename(wdir, newdentry, udir, upper, RENAME_DT_UNKNOWN); if (err) goto out_cleanup; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 8af450b..54162c0 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -113,6 +113,11 @@ static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry, err = vfs_rename(olddir, olddentry, newdir, newdentry, NULL, flags); + /* retry without RENAME_VFS_DTYPE if fs does not support it */ + if (err == -EINVAL && (flags & RENAME_VFS_DTYPE)) + err = vfs_rename(olddir, olddentry, newdir, newdentry, NULL, + flags & RENAME_UAPI_MASK); + if (err) { pr_debug("...rename(%pd2, %pd2, ...) = %i\n", olddentry, newdentry, err); -- 2.7.4 -- 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