···159159rename or unlink will of course be noticed and handled).160160161161162162+Multiple lower layers163163+---------------------164164+165165+Multiple lower layers can now be given using the the colon (":") as a166166+separator character between the directory names. For example:167167+168168+ mount -t overlay overlay -olowerdir=/lower1:/lower2:/lower3 /merged169169+170170+As the example shows, "upperdir=" and "workdir=" may be omitted. In171171+that case the overlay will be read-only.172172+173173+The specified lower directories will be stacked beginning from the174174+rightmost one and going left. In the above example lower1 will be the175175+top, lower2 the middle and lower3 the bottom layer.176176+177177+162178Non-standard behavior163179---------------------164180···212196filesystem are not allowed. If the underlying filesystem is changed,213197the behavior of the overlay is undefined, though it will not result in214198a crash or deadlock.199199+200200+Testsuite201201+---------202202+203203+There's testsuite developed by David Howells at:204204+205205+ git://git.infradead.org/users/dhowells/unionmount-testsuite.git206206+207207+Run as root:208208+209209+ # cd unionmount-testsuite210210+ # ./run --ov
+2-3
fs/overlayfs/copy_up.c
···191191 ovl_set_timestamps(upperdentry, stat);192192193193 return err;194194-195194}196195197196static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,···384385 struct kstat stat;385386 enum ovl_path_type type = ovl_path_type(dentry);386387387387- if (type != OVL_PATH_LOWER)388388+ if (OVL_TYPE_UPPER(type))388389 break;389390390391 next = dget(dentry);···393394 parent = dget_parent(next);394395395396 type = ovl_path_type(parent);396396- if (type != OVL_PATH_LOWER)397397+ if (OVL_TYPE_UPPER(type))397398 break;398399399400 dput(next);
+14-14
fs/overlayfs/dir.c
···118118119119static int ovl_set_opaque(struct dentry *upperdentry)120120{121121- return ovl_do_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0);121121+ return ovl_do_setxattr(upperdentry, OVL_XATTR_OPAQUE, "y", 1, 0);122122}123123124124static void ovl_remove_opaque(struct dentry *upperdentry)125125{126126 int err;127127128128- err = ovl_do_removexattr(upperdentry, ovl_opaque_xattr);128128+ err = ovl_do_removexattr(upperdentry, OVL_XATTR_OPAQUE);129129 if (err) {130130 pr_warn("overlayfs: failed to remove opaque from '%s' (%i)\n",131131 upperdentry->d_name.name, err);···152152 * correct link count. nlink=1 seems to pacify 'find' and153153 * other utilities.154154 */155155- if (type == OVL_PATH_MERGE)155155+ if (OVL_TYPE_MERGE(type))156156 stat->nlink = 1;157157158158 return 0;···506506 struct dentry *opaquedir = NULL;507507 int err;508508509509- if (is_dir) {509509+ if (is_dir && OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) {510510 opaquedir = ovl_check_empty_and_clear(dentry);511511 err = PTR_ERR(opaquedir);512512 if (IS_ERR(opaquedir))···630630 goto out_drop_write;631631632632 type = ovl_path_type(dentry);633633- if (type == OVL_PATH_PURE_UPPER) {633633+ if (OVL_TYPE_PURE_UPPER(type)) {634634 err = ovl_remove_upper(dentry, is_dir);635635 } else {636636 const struct cred *old_cred;···712712 /* Don't copy up directory trees */713713 old_type = ovl_path_type(old);714714 err = -EXDEV;715715- if ((old_type == OVL_PATH_LOWER || old_type == OVL_PATH_MERGE) && is_dir)715715+ if (OVL_TYPE_MERGE_OR_LOWER(old_type) && is_dir)716716 goto out;717717718718 if (new->d_inode) {···725725726726 new_type = ovl_path_type(new);727727 err = -EXDEV;728728- if (!overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir)728728+ if (!overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir)729729 goto out;730730731731 err = 0;732732- if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) {732732+ if (!OVL_TYPE_UPPER(new_type) && !OVL_TYPE_UPPER(old_type)) {733733 if (ovl_dentry_lower(old)->d_inode ==734734 ovl_dentry_lower(new)->d_inode)735735 goto out;736736 }737737- if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) {737737+ if (OVL_TYPE_UPPER(new_type) && OVL_TYPE_UPPER(old_type)) {738738 if (ovl_dentry_upper(old)->d_inode ==739739 ovl_dentry_upper(new)->d_inode)740740 goto out;741741 }742742 } else {743743 if (ovl_dentry_is_opaque(new))744744- new_type = OVL_PATH_UPPER;744744+ new_type = __OVL_PATH_UPPER;745745 else746746- new_type = OVL_PATH_PURE_UPPER;746746+ new_type = __OVL_PATH_UPPER | __OVL_PATH_PURE;747747 }748748749749 err = ovl_want_write(old);···763763 goto out_drop_write;764764 }765765766766- old_opaque = old_type != OVL_PATH_PURE_UPPER;767767- new_opaque = new_type != OVL_PATH_PURE_UPPER;766766+ old_opaque = !OVL_TYPE_PURE_UPPER(old_type);767767+ new_opaque = !OVL_TYPE_PURE_UPPER(new_type);768768769769 if (old_opaque || new_opaque) {770770 err = -ENOMEM;···787787 old_cred = override_creds(override_cred);788788 }789789790790- if (overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) {790790+ if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {791791 opaquedir = ovl_check_empty_and_clear(new);792792 err = PTR_ERR(opaquedir);793793 if (IS_ERR(opaquedir)) {