ovl: make path-type a bitmap
authorMiklos Szeredi <mszeredi@suse.cz>
Fri, 12 Dec 2014 23:59:42 +0000 (00:59 +0100)
committerMiklos Szeredi <mszeredi@suse.cz>
Fri, 12 Dec 2014 23:59:42 +0000 (00:59 +0100)
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>
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/inode.c
fs/overlayfs/overlayfs.h
fs/overlayfs/readdir.c
fs/overlayfs/super.c

index ea10a87191072339b1352c01f0261da054701a9b..a5bfd60f4f6fa13137224d27698a71f286e822fc 100644 (file)
@@ -385,7 +385,7 @@ int ovl_copy_up(struct dentry *dentry)
                struct kstat stat;
                enum ovl_path_type type = ovl_path_type(dentry);
 
-               if (type != OVL_PATH_LOWER)
+               if (OVL_TYPE_UPPER(type))
                        break;
 
                next = dget(dentry);
@@ -394,7 +394,7 @@ int ovl_copy_up(struct dentry *dentry)
                        parent = dget_parent(next);
 
                        type = ovl_path_type(parent);
-                       if (type != OVL_PATH_LOWER)
+                       if (OVL_TYPE_UPPER(type))
                                break;
 
                        dput(next);
index 8ffc4b980f1b68641c17a7bfb67979f205c658b5..ab50bd111feb899bb97e1ad0fbc8ed40d6e97f12 100644 (file)
@@ -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
         * other utilities.
         */
-       if (type == OVL_PATH_MERGE)
+       if (OVL_TYPE_MERGE(type))
                stat->nlink = 1;
 
        return 0;
@@ -630,7 +630,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
                goto out_drop_write;
 
        type = ovl_path_type(dentry);
-       if (type == OVL_PATH_PURE_UPPER) {
+       if (OVL_TYPE_PURE_UPPER(type)) {
                err = ovl_remove_upper(dentry, is_dir);
        } else {
                const struct cred *old_cred;
@@ -712,7 +712,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
        /* Don't copy up directory trees */
        old_type = ovl_path_type(old);
        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;
 
        if (new->d_inode) {
@@ -725,25 +725,25 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
 
                new_type = ovl_path_type(new);
                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;
 
                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 ==
                            ovl_dentry_lower(new)->d_inode)
                                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 ==
                            ovl_dentry_upper(new)->d_inode)
                                goto out;
                }
        } else {
                if (ovl_dentry_is_opaque(new))
-                       new_type = OVL_PATH_UPPER;
+                       new_type = __OVL_PATH_UPPER;
                else
-                       new_type = OVL_PATH_PURE_UPPER;
+                       new_type = __OVL_PATH_UPPER | __OVL_PATH_PURE;
        }
 
        err = ovl_want_write(old);
@@ -763,8 +763,8 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
                        goto out_drop_write;
        }
 
-       old_opaque = old_type != OVL_PATH_PURE_UPPER;
-       new_opaque = new_type != OVL_PATH_PURE_UPPER;
+       old_opaque = !OVL_TYPE_PURE_UPPER(old_type);
+       new_opaque = !OVL_TYPE_PURE_UPPER(new_type);
 
        if (old_opaque || new_opaque) {
                err = -ENOMEM;
@@ -787,7 +787,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
                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);
                err = PTR_ERR(opaquedir);
                if (IS_ERR(opaquedir)) {
index 07d74b24913bdee757377d103427883fb7d12e70..48492f1240ad35d664eccafd181292f56db33bda 100644 (file)
@@ -238,7 +238,10 @@ out:
 static bool ovl_need_xattr_filter(struct dentry *dentry,
                                  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,
@@ -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))
                goto out_drop_write;
 
-       if (type == OVL_PATH_LOWER) {
+       if (!OVL_TYPE_UPPER(type)) {
                err = vfs_getxattr(realpath.dentry, name, NULL, 0);
                if (err < 0)
                        goto out_drop_write;
@@ -321,7 +324,7 @@ out:
 static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
                                  struct dentry *realdentry)
 {
-       if (type != OVL_PATH_LOWER)
+       if (OVL_TYPE_UPPER(type))
                return false;
 
        if (special_file(realdentry->d_inode->i_mode))
index 814bed33dd078c00ade8ed534ae19e969530ccdb..d39eaa8f5e4700a1b4a567466c938c383b813b23 100644 (file)
 struct ovl_entry;
 
 enum ovl_path_type {
-       OVL_PATH_PURE_UPPER,
-       OVL_PATH_UPPER,
-       OVL_PATH_MERGE,
-       OVL_PATH_LOWER,
+       __OVL_PATH_PURE         = (1 << 0),
+       __OVL_PATH_UPPER        = (1 << 1),
+       __OVL_PATH_MERGE        = (1 << 2),
 };
 
+#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;
 
 static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
index 3efa44acf98b0e40a1494222aaba8997ddfc6796..481e44873b65e8e23a246d2ff078ad049e5a1dd9 100644 (file)
@@ -253,8 +253,8 @@ static void ovl_dir_reset(struct file *file)
                ovl_cache_put(od, dentry);
                od->cache = NULL;
        }
-       WARN_ON(!od->is_real && type != OVL_PATH_MERGE);
-       if (od->is_real && type == OVL_PATH_MERGE)
+       WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type));
+       if (od->is_real && OVL_TYPE_MERGE(type))
                od->is_real = false;
 }
 
@@ -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
         */
-       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);
 
                realfile = lockless_dereference(od->upperfile);
@@ -495,8 +495,8 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
        }
        INIT_LIST_HEAD(&od->cursor.l_node);
        od->realfile = realfile;
-       od->is_real = (type != OVL_PATH_MERGE);
-       od->is_upper = (type != OVL_PATH_LOWER);
+       od->is_real = !OVL_TYPE_MERGE(type);
+       od->is_upper = OVL_TYPE_UPPER(type);
        od->cursor.is_cursor = true;
        file->private_data = od;
 
index f16d318b71f8bbe4e77f8a3214e616101848e49c..821719cc85374c417c0228144ecbf6827484dd1e 100644 (file)
@@ -64,22 +64,19 @@ const char *ovl_opaque_xattr = "trusted.overlay.opaque";
 enum ovl_path_type ovl_path_type(struct dentry *dentry)
 {
        struct ovl_entry *oe = dentry->d_fsdata;
+       enum ovl_path_type type = 0;
 
        if (oe->__upperdentry) {
+               type = __OVL_PATH_UPPER;
+
                if (oe->lowerdentry) {
                        if (S_ISDIR(dentry->d_inode->i_mode))
-                               return OVL_PATH_MERGE;
-                       else
-                               return OVL_PATH_UPPER;
-               } else {
-                       if (oe->opaque)
-                               return OVL_PATH_UPPER;
-                       else
-                               return OVL_PATH_PURE_UPPER;
+                               type |= __OVL_PATH_MERGE;
+               } else if (!oe->opaque) {
+                       type |= __OVL_PATH_PURE;
                }
-       } else {
-               return OVL_PATH_LOWER;
        }
+       return type;
 }
 
 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)
 
        enum ovl_path_type type = ovl_path_type(dentry);
 
-       if (type == OVL_PATH_LOWER)
+       if (!OVL_TYPE_UPPER(type))
                ovl_path_lower(dentry, path);
        else
                ovl_path_upper(dentry, path);