Commit 1afaba1e authored by Miklos Szeredi's avatar Miklos Szeredi

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: default avatarMiklos Szeredi <mszeredi@suse.cz>
parent 49c21e1c
...@@ -385,7 +385,7 @@ int ovl_copy_up(struct dentry *dentry) ...@@ -385,7 +385,7 @@ int ovl_copy_up(struct dentry *dentry)
struct kstat stat; struct kstat stat;
enum ovl_path_type type = ovl_path_type(dentry); enum ovl_path_type type = ovl_path_type(dentry);
if (type != OVL_PATH_LOWER) if (OVL_TYPE_UPPER(type))
break; break;
next = dget(dentry); next = dget(dentry);
...@@ -394,7 +394,7 @@ int ovl_copy_up(struct dentry *dentry) ...@@ -394,7 +394,7 @@ int ovl_copy_up(struct dentry *dentry)
parent = dget_parent(next); parent = dget_parent(next);
type = ovl_path_type(parent); type = ovl_path_type(parent);
if (type != OVL_PATH_LOWER) if (OVL_TYPE_UPPER(type))
break; break;
dput(next); dput(next);
......
...@@ -152,7 +152,7 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, ...@@ -152,7 +152,7 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
* correct link count. nlink=1 seems to pacify 'find' and * correct link count. nlink=1 seems to pacify 'find' and
* other utilities. * other utilities.
*/ */
if (type == OVL_PATH_MERGE) if (OVL_TYPE_MERGE(type))
stat->nlink = 1; stat->nlink = 1;
return 0; return 0;
...@@ -630,7 +630,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) ...@@ -630,7 +630,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
goto out_drop_write; goto out_drop_write;
type = ovl_path_type(dentry); type = ovl_path_type(dentry);
if (type == OVL_PATH_PURE_UPPER) { if (OVL_TYPE_PURE_UPPER(type)) {
err = ovl_remove_upper(dentry, is_dir); err = ovl_remove_upper(dentry, is_dir);
} else { } else {
const struct cred *old_cred; const struct cred *old_cred;
...@@ -712,7 +712,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, ...@@ -712,7 +712,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
/* Don't copy up directory trees */ /* Don't copy up directory trees */
old_type = ovl_path_type(old); old_type = ovl_path_type(old);
err = -EXDEV; err = -EXDEV;
if ((old_type == OVL_PATH_LOWER || old_type == OVL_PATH_MERGE) && is_dir) if (OVL_TYPE_MERGE_OR_LOWER(old_type) && is_dir)
goto out; goto out;
if (new->d_inode) { if (new->d_inode) {
...@@ -725,25 +725,25 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, ...@@ -725,25 +725,25 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
new_type = ovl_path_type(new); new_type = ovl_path_type(new);
err = -EXDEV; err = -EXDEV;
if (!overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) if (!overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir)
goto out; goto out;
err = 0; err = 0;
if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) { if (!OVL_TYPE_UPPER(new_type) && !OVL_TYPE_UPPER(old_type)) {
if (ovl_dentry_lower(old)->d_inode == if (ovl_dentry_lower(old)->d_inode ==
ovl_dentry_lower(new)->d_inode) ovl_dentry_lower(new)->d_inode)
goto out; goto out;
} }
if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) { if (OVL_TYPE_UPPER(new_type) && OVL_TYPE_UPPER(old_type)) {
if (ovl_dentry_upper(old)->d_inode == if (ovl_dentry_upper(old)->d_inode ==
ovl_dentry_upper(new)->d_inode) ovl_dentry_upper(new)->d_inode)
goto out; goto out;
} }
} else { } else {
if (ovl_dentry_is_opaque(new)) if (ovl_dentry_is_opaque(new))
new_type = OVL_PATH_UPPER; new_type = __OVL_PATH_UPPER;
else else
new_type = OVL_PATH_PURE_UPPER; new_type = __OVL_PATH_UPPER | __OVL_PATH_PURE;
} }
err = ovl_want_write(old); err = ovl_want_write(old);
...@@ -763,8 +763,8 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, ...@@ -763,8 +763,8 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
goto out_drop_write; goto out_drop_write;
} }
old_opaque = old_type != OVL_PATH_PURE_UPPER; old_opaque = !OVL_TYPE_PURE_UPPER(old_type);
new_opaque = new_type != OVL_PATH_PURE_UPPER; new_opaque = !OVL_TYPE_PURE_UPPER(new_type);
if (old_opaque || new_opaque) { if (old_opaque || new_opaque) {
err = -ENOMEM; err = -ENOMEM;
...@@ -787,7 +787,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, ...@@ -787,7 +787,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
old_cred = override_creds(override_cred); old_cred = override_creds(override_cred);
} }
if (overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) { if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {
opaquedir = ovl_check_empty_and_clear(new); opaquedir = ovl_check_empty_and_clear(new);
err = PTR_ERR(opaquedir); err = PTR_ERR(opaquedir);
if (IS_ERR(opaquedir)) { if (IS_ERR(opaquedir)) {
......
...@@ -238,7 +238,10 @@ int ovl_setxattr(struct dentry *dentry, const char *name, ...@@ -238,7 +238,10 @@ int ovl_setxattr(struct dentry *dentry, const char *name,
static bool ovl_need_xattr_filter(struct dentry *dentry, static bool ovl_need_xattr_filter(struct dentry *dentry,
enum ovl_path_type type) enum ovl_path_type type)
{ {
return type == OVL_PATH_UPPER && S_ISDIR(dentry->d_inode->i_mode); if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER)
return S_ISDIR(dentry->d_inode->i_mode);
else
return false;
} }
ssize_t ovl_getxattr(struct dentry *dentry, const char *name, ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
...@@ -299,7 +302,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name) ...@@ -299,7 +302,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
goto out_drop_write; goto out_drop_write;
if (type == OVL_PATH_LOWER) { if (!OVL_TYPE_UPPER(type)) {
err = vfs_getxattr(realpath.dentry, name, NULL, 0); err = vfs_getxattr(realpath.dentry, name, NULL, 0);
if (err < 0) if (err < 0)
goto out_drop_write; goto out_drop_write;
...@@ -321,7 +324,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name) ...@@ -321,7 +324,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
struct dentry *realdentry) struct dentry *realdentry)
{ {
if (type != OVL_PATH_LOWER) if (OVL_TYPE_UPPER(type))
return false; return false;
if (special_file(realdentry->d_inode->i_mode)) if (special_file(realdentry->d_inode->i_mode))
......
...@@ -12,12 +12,17 @@ ...@@ -12,12 +12,17 @@
struct ovl_entry; struct ovl_entry;
enum ovl_path_type { enum ovl_path_type {
OVL_PATH_PURE_UPPER, __OVL_PATH_PURE = (1 << 0),
OVL_PATH_UPPER, __OVL_PATH_UPPER = (1 << 1),
OVL_PATH_MERGE, __OVL_PATH_MERGE = (1 << 2),
OVL_PATH_LOWER,
}; };
#define OVL_TYPE_UPPER(type) ((type) & __OVL_PATH_UPPER)
#define OVL_TYPE_MERGE(type) ((type) & __OVL_PATH_MERGE)
#define OVL_TYPE_PURE_UPPER(type) ((type) & __OVL_PATH_PURE)
#define OVL_TYPE_MERGE_OR_LOWER(type) \
(OVL_TYPE_MERGE(type) || !OVL_TYPE_UPPER(type))
extern const char *ovl_opaque_xattr; extern const char *ovl_opaque_xattr;
static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry) static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
......
...@@ -253,8 +253,8 @@ static void ovl_dir_reset(struct file *file) ...@@ -253,8 +253,8 @@ static void ovl_dir_reset(struct file *file)
ovl_cache_put(od, dentry); ovl_cache_put(od, dentry);
od->cache = NULL; od->cache = NULL;
} }
WARN_ON(!od->is_real && type != OVL_PATH_MERGE); WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type));
if (od->is_real && type == OVL_PATH_MERGE) if (od->is_real && OVL_TYPE_MERGE(type))
od->is_real = false; od->is_real = false;
} }
...@@ -429,7 +429,7 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end, ...@@ -429,7 +429,7 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
/* /*
* Need to check if we started out being a lower dir, but got copied up * Need to check if we started out being a lower dir, but got copied up
*/ */
if (!od->is_upper && ovl_path_type(dentry) != OVL_PATH_LOWER) { if (!od->is_upper && OVL_TYPE_UPPER(ovl_path_type(dentry))) {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
realfile = lockless_dereference(od->upperfile); realfile = lockless_dereference(od->upperfile);
...@@ -495,8 +495,8 @@ static int ovl_dir_open(struct inode *inode, struct file *file) ...@@ -495,8 +495,8 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
} }
INIT_LIST_HEAD(&od->cursor.l_node); INIT_LIST_HEAD(&od->cursor.l_node);
od->realfile = realfile; od->realfile = realfile;
od->is_real = (type != OVL_PATH_MERGE); od->is_real = !OVL_TYPE_MERGE(type);
od->is_upper = (type != OVL_PATH_LOWER); od->is_upper = OVL_TYPE_UPPER(type);
od->cursor.is_cursor = true; od->cursor.is_cursor = true;
file->private_data = od; file->private_data = od;
......
...@@ -64,22 +64,19 @@ const char *ovl_opaque_xattr = "trusted.overlay.opaque"; ...@@ -64,22 +64,19 @@ const char *ovl_opaque_xattr = "trusted.overlay.opaque";
enum ovl_path_type ovl_path_type(struct dentry *dentry) enum ovl_path_type ovl_path_type(struct dentry *dentry)
{ {
struct ovl_entry *oe = dentry->d_fsdata; struct ovl_entry *oe = dentry->d_fsdata;
enum ovl_path_type type = 0;
if (oe->__upperdentry) { if (oe->__upperdentry) {
type = __OVL_PATH_UPPER;
if (oe->lowerdentry) { if (oe->lowerdentry) {
if (S_ISDIR(dentry->d_inode->i_mode)) if (S_ISDIR(dentry->d_inode->i_mode))
return OVL_PATH_MERGE; type |= __OVL_PATH_MERGE;
else } else if (!oe->opaque) {
return OVL_PATH_UPPER; type |= __OVL_PATH_PURE;
} else {
if (oe->opaque)
return OVL_PATH_UPPER;
else
return OVL_PATH_PURE_UPPER;
} }
} else {
return OVL_PATH_LOWER;
} }
return type;
} }
static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) 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,7 +98,7 @@ enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
enum ovl_path_type type = ovl_path_type(dentry); enum ovl_path_type type = ovl_path_type(dentry);
if (type == OVL_PATH_LOWER) if (!OVL_TYPE_UPPER(type))
ovl_path_lower(dentry, path); ovl_path_lower(dentry, path);
else else
ovl_path_upper(dentry, path); ovl_path_upper(dentry, path);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment