aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-12-12 18:59:44 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2014-12-12 18:59:44 -0500
commit9d7459d834c28f55c82f1737f638a6c90e0c0e0f (patch)
treef84ddaacf935a2bc411b79e637cd73e109a56225 /fs
parent5ef88da56a77bfb3b9631f5e5775f3bff86b6219 (diff)
ovl: multi-layer readdir
If multiple lower layers exist, merge them as well in readdir according to the same rules as merging upper with lower. I.e. take whiteouts and opaque directories into account on all but the lowers layer. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/readdir.c43
-rw-r--r--fs/overlayfs/super.c3
2 files changed, 24 insertions, 22 deletions
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index 481e44873b65..dfef6ca53dfe 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -261,35 +261,34 @@ static void ovl_dir_reset(struct file *file)
261static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list) 261static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list)
262{ 262{
263 int err; 263 int err;
264 struct path lowerpath; 264 struct path realpath;
265 struct path upperpath;
266 struct ovl_readdir_data rdd = { 265 struct ovl_readdir_data rdd = {
267 .ctx.actor = ovl_fill_merge, 266 .ctx.actor = ovl_fill_merge,
268 .list = list, 267 .list = list,
269 .root = RB_ROOT, 268 .root = RB_ROOT,
270 .is_merge = false, 269 .is_merge = false,
271 }; 270 };
272 271 int idx, next;
273 ovl_path_lower(dentry, &lowerpath); 272
274 ovl_path_upper(dentry, &upperpath); 273 for (idx = 0; idx != -1; idx = next) {
275 274 next = ovl_path_next(idx, dentry, &realpath);
276 if (upperpath.dentry) { 275
277 rdd.dir = upperpath.dentry; 276 if (next != -1) {
278 err = ovl_dir_read(&upperpath, &rdd); 277 rdd.dir = realpath.dentry;
279 if (err) 278 err = ovl_dir_read(&realpath, &rdd);
280 goto out; 279 if (err)
281 } 280 break;
282 if (lowerpath.dentry) { 281 } else {
283 /* 282 /*
284 * Insert lowerpath entries before upperpath ones, this allows 283 * Insert lowest layer entries before upper ones, this
285 * offsets to be reasonably constant 284 * allows offsets to be reasonably constant
286 */ 285 */
287 list_add(&rdd.middle, rdd.list); 286 list_add(&rdd.middle, rdd.list);
288 rdd.is_merge = true; 287 rdd.is_merge = true;
289 err = ovl_dir_read(&lowerpath, &rdd); 288 err = ovl_dir_read(&realpath, &rdd);
290 list_del(&rdd.middle); 289 list_del(&rdd.middle);
290 }
291 } 291 }
292out:
293 return err; 292 return err;
294} 293}
295 294
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 07e4c576e93e..c245043aa1b9 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -81,6 +81,9 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry)
81 } else if (!oe->opaque) { 81 } else if (!oe->opaque) {
82 type |= __OVL_PATH_PURE; 82 type |= __OVL_PATH_PURE;
83 } 83 }
84 } else {
85 if (oe->numlower > 1)
86 type |= __OVL_PATH_MERGE;
84 } 87 }
85 return type; 88 return type;
86} 89}