diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2014-12-12 18:59:42 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-12-12 18:59:42 -0500 |
commit | 1afaba1ecb5299cdd0f69b5bad98b0185fe71e79 (patch) | |
tree | 19b3bdd7c514de98a9131665fcb360fda3178d4e | |
parent | 49c21e1cacd74a8c83407c70ad860c994e606e25 (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>
-rw-r--r-- | fs/overlayfs/copy_up.c | 4 | ||||
-rw-r--r-- | fs/overlayfs/dir.c | 22 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 9 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 13 | ||||
-rw-r--r-- | fs/overlayfs/readdir.c | 10 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 19 |
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: | |||
238 | static bool ovl_need_xattr_filter(struct dentry *dentry, | 238 | static 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 | ||
244 | ssize_t ovl_getxattr(struct dentry *dentry, const char *name, | 247 | ssize_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: | |||
321 | static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, | 324 | static 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 @@ | |||
12 | struct ovl_entry; | 12 | struct ovl_entry; |
13 | 13 | ||
14 | enum ovl_path_type { | 14 | enum 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 | |||
21 | extern const char *ovl_opaque_xattr; | 26 | extern const char *ovl_opaque_xattr; |
22 | 27 | ||
23 | static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry) | 28 | static 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"; | |||
64 | enum ovl_path_type ovl_path_type(struct dentry *dentry) | 64 | enum 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 | ||
85 | static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) | 82 | static 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); |