diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 5d21a328fad4..4cd4af097e5c 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -43,6 +43,7 @@ struct ovl_dir_cache { struct ovl_readdir_data { struct dir_context ctx; + const struct file *user_file; struct dentry *dentry; bool is_lowest; struct rb_root *root; @@ -377,7 +378,8 @@ static inline int ovl_dir_read(const struct path *realpath, struct file *realfile; int err; - realfile = ovl_path_open(realpath, O_RDONLY | O_LARGEFILE); + realfile = ovl_path_open_realfile(rdd->user_file, realpath, + O_RDONLY | O_LARGEFILE); if (IS_ERR(realfile)) return PTR_ERR(realfile); @@ -421,13 +423,14 @@ static void ovl_dir_reset(struct file *file) } static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list, - struct rb_root *root) + struct rb_root *root, const struct file *user_file) { int err; struct path realpath; struct ovl_readdir_data rdd = { .ctx.actor = ovl_fill_merge, .ctx.count = INT_MAX, + .user_file = user_file, .dentry = dentry, .list = list, .root = root, @@ -498,9 +501,10 @@ static struct ovl_dir_cache *ovl_dir_cache_check(struct inode *inode, return cache; } -static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) +static struct ovl_dir_cache *ovl_dir_cache_get(struct file *file) { int res; + struct dentry *dentry = file->f_path.dentry; struct ovl_dir_cache *cache; struct inode *inode = d_inode(dentry); @@ -521,7 +525,7 @@ static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) INIT_LIST_HEAD(&cache->entries); cache->root = RB_ROOT; - res = ovl_dir_read_merged(dentry, &cache->entries, &cache->root); + res = ovl_dir_read_merged(dentry, &cache->entries, &cache->root, file); if (res) { ovl_cache_free(&cache->entries); kfree(cache); @@ -665,8 +669,8 @@ static bool ovl_fill_plain(struct dir_context *ctx, const char *name, return true; } -static int ovl_dir_read_impure(const struct path *path, struct list_head *list, - struct rb_root *root) +static int ovl_dir_read_impure(const struct path *path, struct list_head *list, + struct rb_root *root, const struct file *user_file) { int err; struct path realpath; @@ -674,6 +678,7 @@ static int ovl_dir_read_impure(const struct path *path, struct list_head *list, struct ovl_readdir_data rdd = { .ctx.actor = ovl_fill_plain, .ctx.count = INT_MAX, + .user_file = user_file, .list = list, .root = root, }; @@ -710,9 +715,10 @@ static int ovl_dir_read_impure(const struct path *path, struct list_head *list, return 0; } -static struct ovl_dir_cache *ovl_cache_get_impure(const struct path *path) +static struct ovl_dir_cache *ovl_cache_get_impure(struct file *file) { int res; + const struct path *path = &file->f_path; struct dentry *dentry = path->dentry; struct inode *inode = d_inode(dentry); struct ovl_fs *ofs = OVL_FS(dentry->d_sb); @@ -731,7 +737,7 @@ static struct ovl_dir_cache *ovl_cache_get_impure(const struct path *path) return ERR_PTR(-ENOMEM); cache->is_refcounted = false; - res = ovl_dir_read_impure(path, &cache->entries, &cache->root); + res = ovl_dir_read_impure(path, &cache->entries, &cache->root, file); if (res) { ovl_cache_free(&cache->entries); kfree(cache); @@ -852,7 +858,7 @@ static int ovl_iterate_real(struct file *file, struct dir_context *ctx) dput(parent); if (ovl_is_impure_dir(file)) { - rdt.cache = ovl_cache_get_impure(&file->f_path); + rdt.cache = ovl_cache_get_impure(file); if (IS_ERR(rdt.cache)) return PTR_ERR(rdt.cache); } @@ -866,14 +872,13 @@ static int ovl_iterate_real(struct file *file, struct dir_context *ctx) static int ovl_iterate_merged(struct file *file, struct dir_context *ctx) { struct ovl_dir_file *od = file->private_data; - struct dentry *dentry = file->f_path.dentry; struct ovl_cache_entry *p; int err; if (!od->cache) { struct ovl_dir_cache *cache; - cache = ovl_cache_get(dentry); + cache = ovl_dir_cache_get(file); if (IS_ERR(cache)) return PTR_ERR(cache); @@ -1120,7 +1125,7 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) struct rb_root root = RB_ROOT; with_ovl_creds(dentry->d_sb) - err = ovl_dir_read_merged(dentry, list, &root); + err = ovl_dir_read_merged(dentry, list, &root, NULL); if (err) return err;