aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-12-12 18:59:42 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2014-12-12 18:59:42 -0500
commit1afaba1ecb5299cdd0f69b5bad98b0185fe71e79 (patch)
tree19b3bdd7c514de98a9131665fcb360fda3178d4e /fs
parent49c21e1cacd74a8c83407c70ad860c994e606e25 (diff)
ovl: make path-type a bitmap
OVL_PATH_PURE_UPPER -> __OVL_PATH_UPPER | __OVL_PATH_PURE OVL_PATH_UPPER -> __OVL_PATH_UPPER OVL_PATH_MERGE -> __OVL_PATH_UPPER | __OVL_PATH_MERGE OVL_PATH_LOWER -> 0 Multiple R/O layers will allow __OVL_PATH_MERGE without __OVL_PATH_UPPER. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/copy_up.c4
-rw-r--r--fs/overlayfs/dir.c22
-rw-r--r--fs/overlayfs/inode.c9
-rw-r--r--fs/overlayfs/overlayfs.h13
-rw-r--r--fs/overlayfs/readdir.c10
-rw-r--r--fs/overlayfs/super.c19
6 files changed, 41 insertions, 36 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index ea10a8719107..a5bfd60f4f6f 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -385,7 +385,7 @@ int ovl_copy_up(struct dentry *dentry)
385 struct kstat stat; 385 struct kstat stat;
386 enum ovl_path_type type = ovl_path_type(dentry); 386 enum ovl_path_type type = ovl_path_type(dentry);
387 387
388 if (type != OVL_PATH_LOWER) 388 if (OVL_TYPE_UPPER(type))
389 break; 389 break;
390 390
391 next = dget(dentry); 391 next = dget(dentry);
@@ -394,7 +394,7 @@ int ovl_copy_up(struct dentry *dentry)
394 parent = dget_parent(next); 394 parent = dget_parent(next);
395 395
396 type = ovl_path_type(parent); 396 type = ovl_path_type(parent);
397 if (type != OVL_PATH_LOWER) 397 if (OVL_TYPE_UPPER(type))
398 break; 398 break;
399 399
400 dput(next); 400 dput(next);
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 8ffc4b980f1b..ab50bd111feb 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -152,7 +152,7 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
152 * correct link count. nlink=1 seems to pacify 'find' and 152 * correct link count. nlink=1 seems to pacify 'find' and
153 * other utilities. 153 * other utilities.
154 */ 154 */
155 if (type == OVL_PATH_MERGE) 155 if (OVL_TYPE_MERGE(type))
156 stat->nlink = 1; 156 stat->nlink = 1;
157 157
158 return 0; 158 return 0;
@@ -630,7 +630,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
630 goto out_drop_write; 630 goto out_drop_write;
631 631
632 type = ovl_path_type(dentry); 632 type = ovl_path_type(dentry);
633 if (type == OVL_PATH_PURE_UPPER) { 633 if (OVL_TYPE_PURE_UPPER(type)) {
634 err = ovl_remove_upper(dentry, is_dir); 634 err = ovl_remove_upper(dentry, is_dir);
635 } else { 635 } else {
636 const struct cred *old_cred; 636 const struct cred *old_cred;
@@ -712,7 +712,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
712 /* Don't copy up directory trees */ 712 /* Don't copy up directory trees */
713 old_type = ovl_path_type(old); 713 old_type = ovl_path_type(old);
714 err = -EXDEV; 714 err = -EXDEV;
715 if ((old_type == OVL_PATH_LOWER || old_type == OVL_PATH_MERGE) && is_dir) 715 if (OVL_TYPE_MERGE_OR_LOWER(old_type) && is_dir)
716 goto out; 716 goto out;
717 717
718 if (new->d_inode) { 718 if (new->d_inode) {
@@ -725,25 +725,25 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
725 725
726 new_type = ovl_path_type(new); 726 new_type = ovl_path_type(new);
727 err = -EXDEV; 727 err = -EXDEV;
728 if (!overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) 728 if (!overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir)
729 goto out; 729 goto out;
730 730
731 err = 0; 731 err = 0;
732 if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) { 732 if (!OVL_TYPE_UPPER(new_type) && !OVL_TYPE_UPPER(old_type)) {
733 if (ovl_dentry_lower(old)->d_inode == 733 if (ovl_dentry_lower(old)->d_inode ==
734 ovl_dentry_lower(new)->d_inode) 734 ovl_dentry_lower(new)->d_inode)
735 goto out; 735 goto out;
736 } 736 }
737 if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) { 737 if (OVL_TYPE_UPPER(new_type) && OVL_TYPE_UPPER(old_type)) {
738 if (ovl_dentry_upper(old)->d_inode == 738 if (ovl_dentry_upper(old)->d_inode ==
739 ovl_dentry_upper(new)->d_inode) 739 ovl_dentry_upper(new)->d_inode)
740 goto out; 740 goto out;
741 } 741 }
742 } else { 742 } else {
743 if (ovl_dentry_is_opaque(new)) 743 if (ovl_dentry_is_opaque(new))
744 new_type = OVL_PATH_UPPER; 744 new_type = __OVL_PATH_UPPER;
745 else 745 else
746 new_type = OVL_PATH_PURE_UPPER; 746 new_type = __OVL_PATH_UPPER | __OVL_PATH_PURE;
747 } 747 }
748 748
749 err = ovl_want_write(old); 749 err = ovl_want_write(old);
@@ -763,8 +763,8 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
763 goto out_drop_write; 763 goto out_drop_write;
764 } 764 }
765 765
766 old_opaque = old_type != OVL_PATH_PURE_UPPER; 766 old_opaque = !OVL_TYPE_PURE_UPPER(old_type);
767 new_opaque = new_type != OVL_PATH_PURE_UPPER; 767 new_opaque = !OVL_TYPE_PURE_UPPER(new_type);
768 768
769 if (old_opaque || new_opaque) { 769 if (old_opaque || new_opaque) {
770 err = -ENOMEM; 770 err = -ENOMEM;
@@ -787,7 +787,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
787 old_cred = override_creds(override_cred); 787 old_cred = override_creds(override_cred);
788 } 788 }
789 789
790 if (overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) { 790 if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {
791 opaquedir = ovl_check_empty_and_clear(new); 791 opaquedir = ovl_check_empty_and_clear(new);
792 err = PTR_ERR(opaquedir); 792 err = PTR_ERR(opaquedir);
793 if (IS_ERR(opaquedir)) { 793 if (IS_ERR(opaquedir)) {
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 07d74b24913b..48492f1240ad 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -238,7 +238,10 @@ out:
238static bool ovl_need_xattr_filter(struct dentry *dentry, 238static bool ovl_need_xattr_filter(struct dentry *dentry,
239 enum ovl_path_type type) 239 enum ovl_path_type type)
240{ 240{
241 return type == OVL_PATH_UPPER && S_ISDIR(dentry->d_inode->i_mode); 241 if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER)
242 return S_ISDIR(dentry->d_inode->i_mode);
243 else
244 return false;
242} 245}
243 246
244ssize_t ovl_getxattr(struct dentry *dentry, const char *name, 247ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
@@ -299,7 +302,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
299 if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) 302 if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
300 goto out_drop_write; 303 goto out_drop_write;
301 304
302 if (type == OVL_PATH_LOWER) { 305 if (!OVL_TYPE_UPPER(type)) {
303 err = vfs_getxattr(realpath.dentry, name, NULL, 0); 306 err = vfs_getxattr(realpath.dentry, name, NULL, 0);
304 if (err < 0) 307 if (err < 0)
305 goto out_drop_write; 308 goto out_drop_write;
@@ -321,7 +324,7 @@ out:
321static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, 324static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
322 struct dentry *realdentry) 325 struct dentry *realdentry)
323{ 326{
324 if (type != OVL_PATH_LOWER) 327 if (OVL_TYPE_UPPER(type))
325 return false; 328 return false;
326 329
327 if (special_file(realdentry->d_inode->i_mode)) 330 if (special_file(realdentry->d_inode->i_mode))
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 814bed33dd07..d39eaa8f5e47 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -12,12 +12,17 @@
12struct ovl_entry; 12struct ovl_entry;
13 13
14enum ovl_path_type { 14enum ovl_path_type {
15 OVL_PATH_PURE_UPPER, 15 __OVL_PATH_PURE = (1 << 0),
16 OVL_PATH_UPPER, 16 __OVL_PATH_UPPER = (1 << 1),
17 OVL_PATH_MERGE, 17 __OVL_PATH_MERGE = (1 << 2),
18 OVL_PATH_LOWER,
19}; 18};
20 19
20#define OVL_TYPE_UPPER(type) ((type) & __OVL_PATH_UPPER)
21#define OVL_TYPE_MERGE(type) ((type) & __OVL_PATH_MERGE)
22#define OVL_TYPE_PURE_UPPER(type) ((type) & __OVL_PATH_PURE)
23#define OVL_TYPE_MERGE_OR_LOWER(type) \
24 (OVL_TYPE_MERGE(type) || !OVL_TYPE_UPPER(type))
25
21extern const char *ovl_opaque_xattr; 26extern const char *ovl_opaque_xattr;
22 27
23static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry) 28static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index 3efa44acf98b..481e44873b65 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -253,8 +253,8 @@ static void ovl_dir_reset(struct file *file)
253 ovl_cache_put(od, dentry); 253 ovl_cache_put(od, dentry);
254 od->cache = NULL; 254 od->cache = NULL;
255 } 255 }
256 WARN_ON(!od->is_real && type != OVL_PATH_MERGE); 256 WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type));
257 if (od->is_real && type == OVL_PATH_MERGE) 257 if (od->is_real && OVL_TYPE_MERGE(type))
258 od->is_real = false; 258 od->is_real = false;
259} 259}
260 260
@@ -429,7 +429,7 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
429 /* 429 /*
430 * Need to check if we started out being a lower dir, but got copied up 430 * Need to check if we started out being a lower dir, but got copied up
431 */ 431 */
432 if (!od->is_upper && ovl_path_type(dentry) != OVL_PATH_LOWER) { 432 if (!od->is_upper && OVL_TYPE_UPPER(ovl_path_type(dentry))) {
433 struct inode *inode = file_inode(file); 433 struct inode *inode = file_inode(file);
434 434
435 realfile = lockless_dereference(od->upperfile); 435 realfile = lockless_dereference(od->upperfile);
@@ -495,8 +495,8 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
495 } 495 }
496 INIT_LIST_HEAD(&od->cursor.l_node); 496 INIT_LIST_HEAD(&od->cursor.l_node);
497 od->realfile = realfile; 497 od->realfile = realfile;
498 od->is_real = (type != OVL_PATH_MERGE); 498 od->is_real = !OVL_TYPE_MERGE(type);
499 od->is_upper = (type != OVL_PATH_LOWER); 499 od->is_upper = OVL_TYPE_UPPER(type);
500 od->cursor.is_cursor = true; 500 od->cursor.is_cursor = true;
501 file->private_data = od; 501 file->private_data = od;
502 502
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index f16d318b71f8..821719cc8537 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -64,22 +64,19 @@ const char *ovl_opaque_xattr = "trusted.overlay.opaque";
64enum ovl_path_type ovl_path_type(struct dentry *dentry) 64enum ovl_path_type ovl_path_type(struct dentry *dentry)
65{ 65{
66 struct ovl_entry *oe = dentry->d_fsdata; 66 struct ovl_entry *oe = dentry->d_fsdata;
67 enum ovl_path_type type = 0;
67 68
68 if (oe->__upperdentry) { 69 if (oe->__upperdentry) {
70 type = __OVL_PATH_UPPER;
71
69 if (oe->lowerdentry) { 72 if (oe->lowerdentry) {
70 if (S_ISDIR(dentry->d_inode->i_mode)) 73 if (S_ISDIR(dentry->d_inode->i_mode))
71 return OVL_PATH_MERGE; 74 type |= __OVL_PATH_MERGE;
72 else 75 } else if (!oe->opaque) {
73 return OVL_PATH_UPPER; 76 type |= __OVL_PATH_PURE;
74 } else {
75 if (oe->opaque)
76 return OVL_PATH_UPPER;
77 else
78 return OVL_PATH_PURE_UPPER;
79 } 77 }
80 } else {
81 return OVL_PATH_LOWER;
82 } 78 }
79 return type;
83} 80}
84 81
85static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) 82static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe)
@@ -101,7 +98,7 @@ enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
101 98
102 enum ovl_path_type type = ovl_path_type(dentry); 99 enum ovl_path_type type = ovl_path_type(dentry);
103 100
104 if (type == OVL_PATH_LOWER) 101 if (!OVL_TYPE_UPPER(type))
105 ovl_path_lower(dentry, path); 102 ovl_path_lower(dentry, path);
106 else 103 else
107 ovl_path_upper(dentry, path); 104 ovl_path_upper(dentry, path);